diff --git a/.classpath b/.classpath index 4e00818..0c326bc 100644 --- a/.classpath +++ b/.classpath @@ -1,7 +1,9 @@ - - - - - - - + + + + + + + + + diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..9662e6d --- /dev/null +++ b/.travis.yml @@ -0,0 +1,10 @@ +language: java + +addons: + apt: + packages: + - graphviz + +install: ant + +script: ant test diff --git a/Makefile b/Makefile index a44ec41..3fdccf6 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ VERSION:=$(shell git describe --abbrev=6 HEAD | sed 's/R//;s/_/./;s/-/./;s/-.*$$ BALL_TAR_GZ=UMLGraph-$(VERSION).tar.gz ZIPBALL=UMLGraph-$(VERSION).zip DISTDIR=UMLGraph-$(VERSION) -WEBDIR=$(UH)/dds/pubs/web/home/sw/umlgraph-mirror +WEBDIR=$(UH)/dds/pubs/web/home/umlgraph DOCLETSRCPATH=src/main/java/org/umlgraph/doclet DOCLETSRC= \ $(DOCLETSRCPATH)/ClassGraph.java \ @@ -65,7 +65,7 @@ test: ant test testupdate: - sh tools/testupdate.sh + bash tools/testupdate.sh # Create only the static HTML pages static-web: diff --git a/README.md b/README.md new file mode 100644 index 0000000..905ce9e --- /dev/null +++ b/README.md @@ -0,0 +1,69 @@ +# UMLGraph - Declarative Drawing of UML Diagrams + +[![Build Status](https://travis-ci.org/dspinellis/UMLGraph.svg?branch=master)](https://travis-ci.org/dspinellis/UMLGraph) + +*UMLGraph* allows the declarative specification and drawing of UML diagrams. +You can browse the system's documentation +through [this link](http://www.spinellis.gr/umlgraph/doc/index.html), +or print it through [this link](http://www.spinellis.gr/umlgraph/doc/indexw.html). + +In order to run *UMLGraph*, you need to have [GraphViz](https://www.graphviz.org/) +installed in your system path. On most Linux distributions, this can be easily +installed using the regular package manager. + +To compile the Java doclet from the source code run *ant* on the +*build.xml* file. + +If you change the source code, you can run regression tests by +executing *ant test*. + +Visit the project's [home page](http://www.spinellis.gr/umlgraph) for more information. + +## Compatibility + +Currently, only Java 8 is supported by the Doclet. + +In Java 9 the JavaDoc Doclet API changed substantially, and the doclet therefore +needs to be largely rewritten. + +Sorry, this has not happened yet - volunteers for this task are welcome. + +## Development versions + +In order to use development versions, you can use [JitPack](https://jitpack.io/#dspinellis/UMLGraph/master-SNAPSHOT). +Note that as this is compiled on demand, you may sometimes see a "Read timed out" when the package is recompiled, +and it should be fine a few seconds later. And because the master branch can change any time, you may want to use +a versioned snapshot instead (see the Jitpack documentation for details). + +**Gradle**: +``` +repositories { maven { url 'https://jitpack.io' } } +configurations { umlgraph } +dependencies { umlgraph 'com.github.dspinellis:UMLGraph:master-SNAPSHOT' } +javadoc { + doclet = 'org.umlgraph.doclet.UmlGraphDoc' + docletpath = configurations.umlgraph.files.asType(List) + tags("hidden:X", "opt:X", "has:X", "navhas:X", "assoc:X", "navassoc:X", + "composed:X", "navcomposed:X", "stereotype:X", "depend:X") +} +``` + +**Maven**: +``` + + + jitpack.io + https://jitpack.io + + +... + + com.github.dspinellis + UMLGraph + master-SNAPSHOT + compile + +``` + +**Jar download**: + diff --git a/README.mediawiki b/README.mediawiki deleted file mode 100644 index ecd836b..0000000 --- a/README.mediawiki +++ /dev/null @@ -1,23 +0,0 @@ -==UMLGraph - Declarative Drawing of UML Diagrams== - -''UMLGraph'' allows the declarative specification and drawing of -UML diagrams. -You can browse the system's documentation -through [http://umlgraph.org/doc/index.html this link], -or print it through [http://umlgraph.org/doc/indexw.html this link]. - -To install the elements required to run ''UMLGraph'', simply copy -the contents of the ''lib'' directory to a location consistent with -your installation's conventions (for example to /usr/local/lib). - -To compile the Java doclet from the source code run ''ant'' on the -''build.xml'' file. - -If you change the source code, you can run regression tests by -executing ''ant test''. - -Visit the project's [http://www.umlgraph.org home page] for more information. - ----- - -Diomidis Spinellis - November 2005, August 2008, April 2012 diff --git a/README.txt b/README.txt deleted file mode 100644 index f675266..0000000 --- a/README.txt +++ /dev/null @@ -1,21 +0,0 @@ -UMLGraph - Declarative Drawing of UML Diagrams - -UMLGraph allows the declarative specification and drawing of -UML class and sequence diagrams. You can browse the system's -documentation from the doc/index.html page, or print it from -doc/indexw.html. - -To install the elements required to run UMLGraph, simply copy -the contents of the lib directory to a location consistent with -your installation's conventions (for example to /usr/local/lib). - -To compile the Java doclet from the source code run ant on the -build.xml file. - -If you change the source code, you can run regression tests by -executing "ant test". - -Project home page: http://www.umlgraph.org -GitHub page: git@github.com:dspinellis/UMLGraph.git - -Diomidis Spinellis - November 2005, August 2008, April 2012 diff --git a/TODO b/TODO index 42d1f54..7b8d92a 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,3 @@ -When UMLGraph 2.29 comes out use for italic fonts? - http://stackoverflow.com/questions/8609546/umlgraph-not-automatic-integrated-in-javadoc Support for all UML diagrams: state, use-case, etc. diff --git a/build.xml b/build.xml index ebf912c..75af9bd 100644 --- a/build.xml +++ b/build.xml @@ -21,12 +21,12 @@ - + - - + + @@ -64,6 +64,14 @@ + + + + + + + + @@ -78,8 +86,8 @@ - - + + Version is ${VERSION} @@ -119,36 +127,44 @@ class Version { public static String VERSION = "${VERSION}";} - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - + + - - + + + + + + + + + @@ -156,6 +172,7 @@ class Version { public static String VERSION = "${VERSION}";} + diff --git a/doc/Makefile b/doc/Makefile index 9dd11d0..2611a20 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -4,7 +4,7 @@ ROOT=/cygdrive/c PIC2PLOT=pic2plot GS=gs -DESTDIR=/dds/pubs/web/home/sw/umlgraph-mirror +DESTDIR=/dds/pubs/web/home/umlgraph NOTETOOLS=/dds/pubs/Courses/tools GIF := $(shell sed -n 's/.*Soraya Santana de la Fe
  • Jonathan R. Santos
  • Jan Schlüter
  • +
  • Erich Schubert
  • Sebastian Setzer
  • Jörn Guy Süß
  • Andreas Studer
  • diff --git a/doc/bib.bib b/doc/bib.bib index bf14c2c..9d6f40b 100644 --- a/doc/bib.bib +++ b/doc/bib.bib @@ -110,3 +110,14 @@ Note="Available online \url{http://java.dzone.com/articles/reverse-engineer-source-code-u}", Author="Meera Subbarao" } + +@CONFERENCE{SG16, + author={Seifermann, S. and Groenda, H.}, + title={Survey on textual notations for the Unified Modeling Language}, + journal={MODELSWARD 2016 - Proceedings of the 4th International Conference on Model-Driven Engineering and Software Development}, + year={2016}, + pages={28--39}, + note={cited By 0}, + url={https://www.cooperate-project.de/images/publications/MODELSWARD2016.pdf}, + document_type={Conference Paper}, +} diff --git a/doc/cd-oper.xml b/doc/cd-oper.xml index 5fdbe3c..e0c1bf1 100644 --- a/doc/cd-oper.xml +++ b/doc/cd-oper.xml @@ -72,6 +72,14 @@ Example: java -jar /usr/jvm/java-1.5.0/lib/UmlGraph.jar -private Simple.java

    +To generate a diagram of all classes in the package specify as arguments +to the Java invocation the name of the package and the directory where +it resides. +The following example generates a diagram of all UMLGraph classes. + +java -classpath ... org.umlgraph.doclet.UmlGraph -sourcepath src/main/java org.umlgraph.doclet + +

    Specifying some packages before the list of source files will designate those packages as local. When you specify a package list, diff --git a/doc/cd-opt.xml b/doc/cd-opt.xml index 836f8b9..bdee2bb 100644 --- a/doc/cd-opt.xml +++ b/doc/cd-opt.xml @@ -1,9 +1,10 @@ -A number of options contol the operation of UMLGraph +A number of options control the operation of UMLGraph class diagram generator. These can be specified on the command line, and most can also -be specified through javadoc tags within the diagram, affecting all or some elements. +be specified through javadoc @opt tags within the diagram, affecting all or some elements. +Most have a negated version by prefixing an exclamation mark.

    What Gets Drawn

    @@ -27,8 +28,12 @@ be specified through javadoc tags within the diagram, affecting all or some elem in this case it will hide everything (useful in the context of views to selectively unhide some portions of the graph, see the view chapter for further details). +
    -include
    Match classes to include with a non-anchored match. This is weaker than + the -hide option, but can be used to include classes from foreign packages + in the package view (which would by default filter to only include package members).
    -operations
    Show class operations (Java methods)
    -qualify
    Produce fully-qualified class names.
    +
    -qualifyGenerics
    Use fully-qualified class names in Java generics.
    -types
    Add type information to attributes and operations
    -view
    Specify the fully qualified name of a class that contains a view definition. Only the class diagram specified by this view will be generated. @@ -39,6 +44,7 @@ be specified through javadoc tags within the diagram, affecting all or some elem

    Visual Appearance

    -bgcolor
    Specify the graph's background color.
    +
    -autosize
    Fits generated graph to the width of the page/window. Defaults to true.
    -collapsible
    Enhance the javadoc HTML files containing UML diagrams with Javascript that provides a link for showing the (initially collapsed) diagrams.
    -edgecolor
    Specify the color for drawing edges.
    -edgefontcolor
    Specify the font color to use for edge labels.
    @@ -77,9 +83,9 @@ be specified through javadoc tags within the diagram, affecting all or some elem

    All colors can be either a symbolic name (e.g. blue), -a tripple specifying hue-saturation-brightness as values 0-1 +a triple specifying hue-saturation-brightness as values 0-1 (e.g. ".13 0.9 1"), -or a tripple specifying red-green-blue values as hexadecimal +or a triple specifying red-green-blue values as hexadecimal digits prefixed by a # (e.g. "#ff8020"). The symbolic color names are derived from the X Windows System; you can find a complete list in the @@ -182,10 +188,6 @@ When using dot to generate SVG diagrams you should specify UTF-8 as the output encoding, to have guillemots correctly appearing in the resulting SVG.

    -
    -verbose2
    Will print on the standard output details regarding -the progress of graph generation. -(Note that -verbose is a javadoc option with a different meaning). -
    diff --git a/doc/ceg-adv.xml b/doc/ceg-adv.xml index 29c5075..1dc87f5 100644 --- a/doc/ceg-adv.xml +++ b/doc/ceg-adv.xml @@ -31,7 +31,7 @@ class SetTopController implements URLStreamHandler { void connect() {} } -/** @depend - - SetTopController */ +/** @depend - <friend> - SetTopController */ class ChannelIterator {} interface URLStreamHandler { diff --git a/doc/ceg-er.xml b/doc/ceg-er.xml index 19ab1c4..16783ec 100644 --- a/doc/ceg-er.xml +++ b/doc/ceg-er.xml @@ -1,11 +1,12 @@ -The following was generated by annotating the source code of the -SQO-OSS project. +The following was generated by annotating the +source code of the +Alitheia Core project. Georgios Gousios, who created it, wrote:

    -I've used UMLgraph to generate an E-R diagram out of the DAOs we use in SQO-OSS. I've just annotated a few classes with @assoc tags, removed the super class DAObject from all entities with sed, did some tweaking by hand in the .dot output, et voila, an E-R depicting almost 30 classes in less than 30 minutes! +I've used UMLgraph to generate an E-R diagram out of the DAOs we use in Alitheia Core. I've just annotated a few classes with @assoc tags, removed the super class DAObject from all entities with sed, did some tweaking by hand in the .dot output, et voila, an E-R depicting almost 30 classes in less than 30 minutes!

    diff --git a/doc/ceg-infer.xml b/doc/ceg-infer.xml index dc8e0e9..379ecf9 100644 --- a/doc/ceg-infer.xml +++ b/doc/ceg-infer.xml @@ -20,8 +20,8 @@ class UMLOptions {} class Person { House[] houses; - List dogs; - + List<Dog> dogs; + public Room getFavouriteRoom(House house) {} } @@ -29,7 +29,7 @@ class Person { * @opt inferreltype composed */ class House { - Map nameRoomMap; + Map<String, Room> nameRoomMap; } class Room {} @@ -37,7 +37,6 @@ class Room {} class Dog { Person owner; } - UML diagram with relationship inference diff --git a/doc/ceg-mv.xml b/doc/ceg-mv.xml index 4e59ab6..1da7d42 100644 --- a/doc/ceg-mv.xml +++ b/doc/ceg-mv.xml @@ -61,7 +61,7 @@ class DataOperation extends Element {} # Author: Vadim Nasardinov (vadimn@redhat.com) # Since: 2004-05-26 -# See: http://www.spinellis.gr/sw/umlgraph/doc/ceg-mv.html +# See: http://www.spinellis.gr/umlgraph/doc/ceg-mv.html # Requires: graphviz # Requires: javadoc @@ -93,18 +93,18 @@ clean: build/%.dot : %.java mkdir -p $(dir $@) - $(jd) $(jd_flags) $(detailed_flags) -output $@ $< + $(jd) $(jd_flags) $(detailed_flags) -output $@ $< build/%-small.dot : %.java mkdir -p $(dir $@) - $(jd) $(jd_flags) -output $@ $< + $(jd) $(jd_flags) -output $@ $< %.png : %.dot - dot -Nheight=0.2 -Elabelfontcolor=DarkSlateBlue -Elabelfontsize=8 -Tpng -o $@ $< + dot -Nheight=0.2 -Elabelfontcolor=DarkSlateBlue -Elabelfontsize=8 -Tpng -o $@ $< build/%.png : %.fig mkdir -p $(dir $@) - fig2dev -L png -S 4 $< $@ + fig2dev -L png -S 4 $< $@ dot: $(dot_files) @@ -112,7 +112,7 @@ png: $(png_files) build/%.png : %.png mkdir -p $(dir $@) - cp $< $@ + cp $< $@ # Example usage: # make debug-java_files diff --git a/doc/uml-184.xml b/doc/uml-184.xml index a4adb65..7d0f3d3 100644 --- a/doc/uml-184.xml +++ b/doc/uml-184.xml @@ -30,7 +30,7 @@ async(); message(S,W,"liftReceiver"); sync(); active(S); message(W,S,"setDialTone()"); async(); message(S,W,"*dialDigit(d)"); sync(); -lconstraint(W,"{dialing.executionTime < 30s}"); +lconstraint(W,"{dialing.executionTime < 30s}"); active(W); message(W,W,"routeCalls(s,n)"); inactive(W); diff --git a/doc/ver.xml b/doc/ver.xml index 86c2814..b75d125 100644 --- a/doc/ver.xml +++ b/doc/ver.xml @@ -3,6 +3,21 @@

    Version 5.7 Under development
    +
      +
    • The @opt include option can be used to include classes from +foreign packages in the package view (unless hidden with @opt hide).
    • +
    • You can now also use @opt in package-info.java.
    • +
    • Added -qualifyGenerics option to separately control the inclusion of +package names for the class (-qualify) and its generics. In particular +this works well with -qualify -postfixpackage (and -!qualifyGenerics).
      +To get the old -qualify behavior, you need to add -qualifyGenerics, +the default is off, and it will not inherit from -qualify.
    • +
    • Better handling of complex names with generics and inner classes such as pkg.Outer<T>.Inner.
    • +
    • Use <i> tags for italic, because the old font naming approach does not work with SVG anymore. +Replace -nodefontabstractname and -nodefontclassabstractname +with a simple flag -nodefontabstractitalic instead.
    • +
    • Added -hideprivateinner to hide all private inner classes.
    • +
    Version 5.6 2012-05-31
    diff --git a/pom.template.xml b/pom.template.xml index 848ee33..ada93c4 100644 --- a/pom.template.xml +++ b/pom.template.xml @@ -10,7 +10,7 @@ UMLGraph ${version} Declarative Drawing of UML Diagrams - http://www.umlgraph.org + http://www.spinellis.gr/umlgraph diff --git a/pom.xml b/pom.xml index 1e0e4d0..6c9edd3 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ UMLGraph 5.7.3-SNAPSHOT Declarative Drawing of UML Diagrams - http://www.umlgraph.org + http://www.spinellis.gr/umlgraph @@ -128,6 +128,7 @@ ${project.build.directory}${file.separator}${project.build.finalName}.jar -inferrel -inferdep + -autosize -collapsible -hide java.* -collpackages diff --git a/src/main/java/org/umlgraph/doclet/ClassGraph.java b/src/main/java/org/umlgraph/doclet/ClassGraph.java index 7d2d1a1..fe2e21e 100644 --- a/src/main/java/org/umlgraph/doclet/ClassGraph.java +++ b/src/main/java/org/umlgraph/doclet/ClassGraph.java @@ -19,11 +19,21 @@ package org.umlgraph.doclet; +import static org.umlgraph.doclet.StringUtil.buildRelativePathFromClassNames; +import static org.umlgraph.doclet.StringUtil.escape; +import static org.umlgraph.doclet.StringUtil.fmt; +import static org.umlgraph.doclet.StringUtil.guilWrap; +import static org.umlgraph.doclet.StringUtil.guillemize; +import static org.umlgraph.doclet.StringUtil.htmlNewline; +import static org.umlgraph.doclet.StringUtil.removeTemplate; +import static org.umlgraph.doclet.StringUtil.splitPackageClass; +import static org.umlgraph.doclet.StringUtil.tokenize; + import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; -import java.io.OutputStream; import java.io.IOException; +import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.ArrayList; @@ -33,7 +43,6 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.regex.Pattern; import com.sun.javadoc.ClassDoc; import com.sun.javadoc.ConstructorDoc; @@ -61,23 +70,16 @@ import com.sun.javadoc.WildcardType; * @author Diomidis Spinellis */ class ClassGraph { - protected static final char FILE_SEPARATOR = '/'; - enum Font { - NORMAL, ABSTRACT, CLASS, CLASS_ABSTRACT, TAG, PACKAGE - } enum Align { - LEFT, CENTER, RIGHT + LEFT, CENTER, RIGHT; + + public final String lower; + + private Align() { + this.lower = toString().toLowerCase(); + } }; - public static Map associationMap = new HashMap(); - static { - associationMap.put(RelationType.ASSOC, "arrowhead=none"); - associationMap.put(RelationType.NAVASSOC, "arrowhead=open"); - associationMap.put(RelationType.HAS, "arrowhead=none, arrowtail=ediamond, dir=both"); - associationMap.put(RelationType.NAVHAS, "arrowhead=open, arrowtail=ediamond, dir=both"); - associationMap.put(RelationType.COMPOSED, "arrowhead=none, arrowtail=diamond, dir=both"); - associationMap.put(RelationType.NAVCOMPOSED, "arrowhead=open, arrowtail=diamond, dir=both"); - associationMap.put(RelationType.DEPEND, "arrowhead=open, style=dashed"); - } + protected Map classnames = new HashMap(); protected Set rootClasses; protected Map rootClassdocs = new HashMap(); @@ -90,7 +92,7 @@ class ClassGraph { // used only when generating context class diagrams in UMLDoc, to generate the proper // relative links to other classes in the image map - protected Doc contextDoc; + protected final String contextPackageName; /** * Create a new ClassGraph.

    The packages passed as an @@ -105,7 +107,6 @@ class ClassGraph { this.optionProvider = optionProvider; this.collectionClassDoc = root.classNamed("java.util.Collection"); this.mapClassDoc = root.classNamed("java.util.Map"); - this.contextDoc = contextDoc; // to gather the packages containing specified classes, loop thru them and gather // package definitions. User root.specifiedPackages is not safe, since the user @@ -113,123 +114,60 @@ class ClassGraph { rootClasses = new HashSet(); for (ClassDoc classDoc : root.classes()) { rootClasses.add(classDoc.qualifiedName()); - rootClassdocs.put(classDoc.qualifiedName(), classDoc); + rootClassdocs.put(classDoc.qualifiedName(), classDoc); } + // determine the context path, relative to the root + if (contextDoc instanceof ClassDoc) + contextPackageName = ((ClassDoc) contextDoc).containingPackage().name(); + else if (contextDoc instanceof PackageDoc) + contextPackageName = ((PackageDoc) contextDoc).name(); + else + contextPackageName = null; // Not available + Options opt = optionProvider.getGlobalOptions(); - if (opt.compact) { - linePrefix = ""; - linePostfix = ""; - } else { - linePrefix = "\t"; - linePostfix = "\n"; - } + linePrefix = opt.compact ? "" : "\t"; + linePostfix = opt.compact ? "" : "\n"; } /** Return the class's name, possibly by stripping the leading path */ - private String qualifiedName(Options opt, String r) { - if (!opt.showQualified) { - // Create readable string by stripping leading path - for (;;) { - int dotpos = r.lastIndexOf('.'); - if (dotpos == -1) break; // Work done! - /* - * Change all occurences of - * "p1.p2.myClass" into - * "myClass" - */ - int start = dotpos; - while (start > 0 && Character.isJavaIdentifierPart(r.charAt(start - 1))) - start--; - r = r.substring(0, start) + r.substring(dotpos + 1); + private static String qualifiedName(Options opt, String r) { + if (opt.hideGenerics) + r = removeTemplate(r); + // Fast path - nothing to do: + if (opt.showQualified && (opt.showQualifiedGenerics || r.indexOf('<') < 0)) + return r; + StringBuilder buf = new StringBuilder(r.length()); + qualifiedNameInner(opt, r, buf, 0, !opt.showQualified); + return buf.toString(); + } + + private static int qualifiedNameInner(Options opt, String r, StringBuilder buf, int last, boolean strip) { + strip = strip && last < r.length() && Character.isLowerCase(r.charAt(last)); + for (int i = last; i < r.length(); i++) { + char c = r.charAt(i); + if (c == '.' || c == '$') { + if (strip) + last = i + 1; // skip dot + strip = strip && last < r.length() && Character.isLowerCase(r.charAt(last)); + continue; } + if (Character.isJavaIdentifierPart(c)) + continue; + buf.append(r, last, i); + last = i; + // Handle nesting of generics + if (c == '<') { + buf.append('<'); + i = last = qualifiedNameInner(opt, r, buf, ++last, !opt.showQualifiedGenerics); + buf.append('>'); + } else if (c == '>') + return i + 1; } - return r; - } - - /** - * Escape <, >, and & characters in the string with - * the corresponding HTML entity code. - */ - private String escape(String s) { - final Pattern toEscape = Pattern.compile("[&<>]"); - - if (toEscape.matcher(s).find()) { - StringBuffer sb = new StringBuffer(s); - for (int i = 0; i < sb.length();) { - switch (sb.charAt(i)) { - case '&': - sb.replace(i, i + 1, "&"); - i += "&".length(); - break; - case '<': - sb.replace(i, i + 1, "<"); - i += "<".length(); - break; - case '>': - sb.replace(i, i + 1, ">"); - i += ">".length(); - break; - default: - i++; - } - } - return sb.toString(); - } else - return s; - } - - /** - * Convert embedded newlines into HTML line breaks - */ - private String htmlNewline(String s) { - if (s.indexOf('\n') == -1) - return (s); - - StringBuffer sb = new StringBuffer(s); - for (int i = 0; i < sb.length();) { - if (sb.charAt(i) == '\n') { - sb.replace(i, i + 1, "
    "); - i += "
    ".length(); - } else - i++; - } - return sb.toString(); - } - - - /** - * Convert < and > characters in the string to the respective guillemot characters. - */ - private String guillemize(Options opt, String s) { - StringBuffer r = new StringBuffer(s); - for (int i = 0; i < r.length();) - switch (r.charAt(i)) { - case '<': - r.replace(i, i + 1, opt.guilOpen); - i += opt.guilOpen.length(); - break; - case '>': - r.replace(i, i + 1, opt.guilClose); - i += opt.guilClose.length(); - break; - default: - i++; - break; - } - return r.toString(); - } - - /** - * Wraps a string in Guillemot (or an ASCII substitute) characters. - * - * @param str the String to be wrapped. - * @return the wrapped String. - */ - private String guilWrap(Options opt, String str) { - return opt.guilOpen + str + opt.guilClose; + buf.append(r, last, r.length()); + return r.length(); } /** @@ -237,67 +175,46 @@ class ClassGraph { * any stereotypes */ private String visibility(Options opt, ProgramElementDoc e) { - if (!opt.showVisibility) - return " "; - if (e.isPrivate()) - return "- "; - else if (e.isPublic()) - return "+ "; - else if (e.isProtected()) - return "# "; - else if (e.isPackagePrivate()) - return "~ "; - else - return " "; + return opt.showVisibility ? Visibility.get(e).symbol : " "; } /** Print the method parameter p */ private String parameter(Options opt, Parameter p[]) { - String par = ""; + StringBuilder par = new StringBuilder(1000); for (int i = 0; i < p.length; i++) { - par += p[i].name() + typeAnnotation(opt, p[i].type()); + par.append(p[i].name() + typeAnnotation(opt, p[i].type())); if (i + 1 < p.length) - par += ", "; + par.append(", "); } - return par; + return par.toString(); } /** Print a a basic type t */ - private String type(Options opt, Type t) { - String type = ""; - if (opt.showQualified) - type = t.qualifiedTypeName(); - else - type = t.typeName(); - type += typeParameters(opt, t.asParameterizedType()); - return type; + private String type(Options opt, Type t, boolean generics) { + return ((generics ? opt.showQualifiedGenerics : opt.showQualified) ? // + t.qualifiedTypeName() : t.typeName()) // + + (opt.hideGenerics ? "" : typeParameters(opt, t.asParameterizedType())); } /** Print the parameters of the parameterized type t */ private String typeParameters(Options opt, ParameterizedType t) { - String tp = ""; if (t == null) - return tp; + return ""; + StringBuffer tp = new StringBuffer(1000).append("<"); Type args[] = t.typeArguments(); - tp += "<"; for (int i = 0; i < args.length; i++) { - tp += type(opt, args[i]); + tp.append(type(opt, args[i], true)); if (i != args.length - 1) - tp += ", "; + tp.append(", "); } - tp += ">"; - return tp; + return tp.append(">").toString(); } /** Annotate an field/argument with its type t */ private String typeAnnotation(Options opt, Type t) { - String ta = ""; if (t.typeName().equals("void")) - return ta; - ta += " : "; - ta += type(opt, t); - ta += t.dimension(); - return ta; + return ""; + return " : " + type(opt, t, false) + t.dimension(); } /** Print the class's attributes fd */ @@ -305,9 +222,8 @@ class ClassGraph { for (FieldDoc f : fd) { if (hidden(f)) continue; - String att = ""; stereotype(opt, f, Align.LEFT); - att = visibility(opt, f) + f.name(); + String att = visibility(opt, f) + f.name(); if (opt.showType) att += typeAnnotation(opt, f.type()); tableLine(Align.LEFT, att); @@ -328,15 +244,11 @@ class ClassGraph { if (hidden(cd)) continue; stereotype(opt, cd, Align.LEFT); - String cs = visibility(opt, cd) + cd.name(); - if (opt.showType) { - cs += "(" + parameter(opt, cd.parameters()) + ")"; - } else { - cs += "()"; - } + String cs = visibility(opt, cd) + cd.name() // + + (opt.showType ? "(" + parameter(opt, cd.parameters()) + ")" : "()"); tableLine(Align.LEFT, cs); - printed = true; tagvalue(opt, cd); + printed = true; } return printed; } @@ -351,14 +263,10 @@ class ClassGraph { if (md.name().equals("") && md.isStatic() && md.isPackagePrivate()) continue; stereotype(opt, md, Align.LEFT); - String op = visibility(opt, md) + md.name(); - if (opt.showType) { - op += "(" + parameter(opt, md.parameters()) + ")" - + typeAnnotation(opt, md.returnType()); - } else { - op += "()"; - } - tableLine(Align.LEFT, op, opt, md.isAbstract() ? Font.ABSTRACT : Font.NORMAL); + String op = visibility(opt, md) + md.name() + // + (opt.showType ? "(" + parameter(opt, md.parameters()) + ")" + typeAnnotation(opt, md.returnType()) + : "()"); + tableLine(Align.LEFT, (md.isAbstract() ? Font.ABSTRACT : Font.NORMAL).wrap(opt, op)); printed = true; tagvalue(opt, md); @@ -368,10 +276,14 @@ class ClassGraph { /** Print the common class node's properties */ private void nodeProperties(Options opt) { - w.print(", fontname=\"" + opt.nodeFontName + "\""); - w.print(", fontcolor=\"" + opt.nodeFontColor + "\""); - w.print(", fontsize=" + opt.nodeFontSize); - w.print(opt.shape.graphvizAttribute()); + Options def = opt.getGlobalOptions(); + if (opt.nodeFontName != def.nodeFontName) + w.print(",fontname=\"" + opt.nodeFontName + "\""); + if (opt.nodeFontColor != def.nodeFontColor) + w.print(",fontcolor=\"" + opt.nodeFontColor + "\""); + if (opt.nodeFontSize != def.nodeFontSize) + w.print(",fontsize=" + fmt(opt.nodeFontSize)); + w.print(opt.shape.style); w.println("];"); } @@ -388,12 +300,12 @@ class ClassGraph { return; for (Tag tag : tags) { - String t[] = StringUtil.tokenize(tag.text()); + String t[] = tokenize(tag.text()); if (t.length != 2) { System.err.println("@tagvalue expects two fields: " + tag.text()); continue; } - tableLine(Align.RIGHT, "{" + t[0] + " = " + t[1] + "}", opt, Font.TAG); + tableLine(Align.RIGHT, Font.TAG.wrap(opt, "{" + t[0] + " = " + t[1] + "}")); } } @@ -403,7 +315,7 @@ class ClassGraph { */ private void stereotype(Options opt, Doc c, Align align) { for (Tag tag : c.tags("stereotype")) { - String t[] = StringUtil.tokenize(tag.text()); + String t[] = tokenize(tag.text()); if (t.length != 1) { System.err.println("@stereotype expects one field: " + tag.text()); continue; @@ -414,42 +326,39 @@ class ClassGraph { /** Return true if c has a @hidden tag associated with it */ private boolean hidden(ProgramElementDoc c) { - Tag tags[] = c.tags("hidden"); - if (tags.length > 0) + if (c.tags("hidden").length > 0 || c.tags("view").length > 0) return true; - tags = c.tags("view"); - if (tags.length > 0) - return true; - Options opt; - if(c instanceof ClassDoc) - opt = optionProvider.getOptionsFor((ClassDoc) c); - else - opt = optionProvider.getOptionsFor(c.containingClass()); - return opt.matchesHideExpression(c.toString()); + Options opt = optionProvider.getOptionsFor(c instanceof ClassDoc ? (ClassDoc) c : c.containingClass()); + return opt.matchesHideExpression(c.toString()) // + || (opt.hidePrivateInner && c instanceof ClassDoc && c.isPrivate() && ((ClassDoc) c).containingClass() != null); } - - protected ClassInfo getClassInfo(String className) { - return classnames.get(removeTemplate(className)); + + protected ClassInfo getClassInfo(ClassDoc cd, boolean create) { + return getClassInfo(cd, cd.toString(), create); } - - private ClassInfo newClassInfo(String className, boolean printed, boolean hidden) { - ClassInfo ci = new ClassInfo(printed, hidden); - classnames.put(removeTemplate(className), ci); - return ci; + + protected ClassInfo getClassInfo(String className, boolean create) { + return getClassInfo(null, className, create); + } + + protected ClassInfo getClassInfo(ClassDoc cd, String className, boolean create) { + className = removeTemplate(className); + ClassInfo ci = classnames.get(className); + if (ci == null && create) { + boolean hidden = cd != null ? hidden(cd) : optionProvider.getOptionsFor(className).matchesHideExpression(className); + ci = new ClassInfo(hidden); + classnames.put(className, ci); + } + return ci; } /** Return true if the class name is associated to an hidden class or matches a hide expression */ - private boolean hidden(String s) { - ClassInfo ci = getClassInfo(s); - Options opt = optionProvider.getOptionsFor(s); - if(ci != null) - return ci.hidden || opt.matchesHideExpression(s); - else - return opt.matchesHideExpression(s); + private boolean hidden(String className) { + className = removeTemplate(className); + ClassInfo ci = classnames.get(className); + return ci != null ? ci.hidden : optionProvider.getOptionsFor(className).matchesHideExpression(className); } - - /** * Prints the class if needed. *

    @@ -458,161 +367,122 @@ class ClassGraph { * relative links in diagrams for UMLDoc */ public String printClass(ClassDoc c, boolean rootClass) { - ClassInfo ci; - boolean toPrint; + ClassInfo ci = getClassInfo(c, true); + if(ci.nodePrinted || ci.hidden) + return ci.name; Options opt = optionProvider.getOptionsFor(c); - + if (c.isEnum() && !opt.showEnumerations) + return ci.name; String className = c.toString(); - if ((ci = getClassInfo(className)) != null) - toPrint = !ci.nodePrinted; - else { - toPrint = true; - ci = newClassInfo(className, true, hidden(c)); - } - if (toPrint && !hidden(c) && (!c.isEnum() || opt.showEnumerations)) { - // Associate classname's alias - String r = className; - w.println("\t// " + r); - // Create label - w.print("\t" + ci.name + " [label="); + // Associate classname's alias + w.println(linePrefix + "// " + className); + // Create label + w.print(linePrefix + ci.name + " [label="); - boolean showMembers = + boolean showMembers = (opt.showAttributes && c.fields().length > 0) || (c.isEnum() && opt.showEnumConstants && c.enumConstants().length > 0) || (opt.showOperations && c.methods().length > 0) || (opt.showConstructors && c.constructors().length > 0); - - externalTableStart(opt, c.qualifiedName(), classToUrl(c, rootClass)); - // Calculate the number of innerTable rows we will emmit - int nRows = 1; - if (showMembers) { - if (opt.showAttributes) - nRows++; - else if(!c.isEnum() && (opt.showConstructors || opt.showOperations)) - nRows++; - if (c.isEnum() && opt.showEnumConstants) - nRows++; - if (!c.isEnum() && (opt.showConstructors || opt.showOperations)) - nRows++; - } + final String url = classToUrl(c, rootClass); + externalTableStart(opt, c.qualifiedName(), url); - firstInnerTableStart(opt, nRows); - if (c.isInterface()) - tableLine(Align.CENTER, guilWrap(opt, "interface")); - if (c.isEnum()) - tableLine(Align.CENTER, guilWrap(opt, "enumeration")); - stereotype(opt, c, Align.CENTER); - Font font = c.isAbstract() && !c.isInterface() ? Font.CLASS_ABSTRACT : Font.CLASS; - String qualifiedName = qualifiedName(opt, r); - int startTemplate = qualifiedName.indexOf('<'); - int idx = 0; - if(startTemplate < 0) - idx = qualifiedName.lastIndexOf('.'); - else - idx = qualifiedName.lastIndexOf('.', startTemplate); - if (opt.showComment) - tableLine(Align.LEFT, htmlNewline(escape(c.commentText())), opt, Font.CLASS); - else if(opt.postfixPackage && idx > 0 && idx < (qualifiedName.length() - 1)) { - String packageName = qualifiedName.substring(0, idx); - String cn = className.substring(idx + 1); - tableLine(Align.CENTER, escape(cn), opt, font); - tableLine(Align.CENTER, packageName, opt, Font.PACKAGE); - } else { - tableLine(Align.CENTER, escape(qualifiedName), opt, font); - } - tagvalue(opt, c); - firstInnerTableEnd(opt, nRows); - - /* - * Warning: The boolean expressions guarding innerTableStart() - * in this block, should match those in the code block above - * marked: "Calculate the number of innerTable rows we will emmit" - */ - if (showMembers) { - if (opt.showAttributes) { - innerTableStart(); - FieldDoc[] fields = c.fields(); - // if there are no fields, print an empty line to generate proper HTML - if (fields.length == 0) - tableLine(Align.LEFT, ""); - else - attributes(opt, c.fields()); - innerTableEnd(); - } else if(!c.isEnum() && (opt.showConstructors || opt.showOperations)) { - // show an emtpy box if we don't show attributes but - // we show operations - innerTableStart(); - tableLine(Align.LEFT, ""); - innerTableEnd(); - } - if (c.isEnum() && opt.showEnumConstants) { - innerTableStart(); - FieldDoc[] ecs = c.enumConstants(); - // if there are no constants, print an empty line to generate proper HTML - if (ecs.length == 0) { - tableLine(Align.LEFT, ""); - } else { - for (FieldDoc fd : c.enumConstants()) { - tableLine(Align.LEFT, fd.name()); - } - } - innerTableEnd(); - } - if (!c.isEnum() && (opt.showConstructors || opt.showOperations)) { - innerTableStart(); - boolean printedLines = false; - if (opt.showConstructors) - printedLines |= operations(opt, c.constructors()); - if (opt.showOperations) - printedLines |= operations(opt, c.methods()); - - if (!printedLines) - // if there are no operations nor constructors, - // print an empty line to generate proper HTML - tableLine(Align.LEFT, ""); - - innerTableEnd(); - } - } - externalTableEnd(); - w.print(", URL=\"" + classToUrl(c, rootClass) + "\""); - nodeProperties(opt); - - // If needed, add a note for this node - int ni = 0; - for (Tag t : c.tags("note")) { - String noteName = "n" + ni + "c" + ci.name; - w.print("\t// Note annotation\n"); - w.print("\t" + noteName + " [label="); - externalTableStart(UmlGraph.getCommentOptions(), c.qualifiedName(), classToUrl(c, rootClass)); - innerTableStart(); - tableLine(Align.LEFT, htmlNewline(escape(t.text())), UmlGraph.getCommentOptions(), Font.CLASS); - innerTableEnd(); - externalTableEnd(); - nodeProperties(UmlGraph.getCommentOptions()); - w.print("\t" + noteName + " -> " + relationNode(c) + "[arrowhead=none];\n"); - ni++; - } - ci.nodePrinted = true; + firstInnerTableStart(opt); + if (c.isInterface()) + tableLine(Align.CENTER, guilWrap(opt, "interface")); + if (c.isEnum()) + tableLine(Align.CENTER, guilWrap(opt, "enumeration")); + stereotype(opt, c, Align.CENTER); + Font font = c.isAbstract() && !c.isInterface() ? Font.CLASS_ABSTRACT : Font.CLASS; + String qualifiedName = qualifiedName(opt, className); + int idx = splitPackageClass(qualifiedName); + if (opt.showComment) + tableLine(Align.LEFT, Font.CLASS.wrap(opt, htmlNewline(escape(c.commentText())))); + else if (opt.postfixPackage && idx > 0 && idx < (qualifiedName.length() - 1)) { + String packageName = qualifiedName.substring(0, idx); + String cn = qualifiedName.substring(idx + 1); + tableLine(Align.CENTER, font.wrap(opt, escape(cn))); + tableLine(Align.CENTER, Font.PACKAGE.wrap(opt, packageName)); + } else { + tableLine(Align.CENTER, font.wrap(opt, escape(qualifiedName))); } - return ci.name; - } + tagvalue(opt, c); + firstInnerTableEnd(opt); - private String getNodeName(ClassDoc c) { - String className = c.toString(); - ClassInfo ci = getClassInfo(className); - if (ci == null) - ci = newClassInfo(className, false, hidden(c)); - return ci.name; - } - - /** Return a class's internal name */ - private String getNodeName(String c) { - ClassInfo ci = getClassInfo(c); + /* + * Warning: The boolean expressions guarding innerTableStart() + * in this block, should match those in the code block above + * marked: "Calculate the number of innerTable rows we will emmit" + */ + if (showMembers) { + if (opt.showAttributes) { + innerTableStart(); + FieldDoc[] fields = c.fields(); + // if there are no fields, print an empty line to generate proper HTML + if (fields.length == 0) + tableLine(Align.LEFT, ""); + else + attributes(opt, c.fields()); + innerTableEnd(); + } else if(!c.isEnum() && (opt.showConstructors || opt.showOperations)) { + // show an emtpy box if we don't show attributes but + // we show operations + innerTableStart(); + tableLine(Align.LEFT, ""); + innerTableEnd(); + } + if (c.isEnum() && opt.showEnumConstants) { + innerTableStart(); + FieldDoc[] ecs = c.enumConstants(); + // if there are no constants, print an empty line to generate proper HTML + if (ecs.length == 0) { + tableLine(Align.LEFT, ""); + } else { + for (FieldDoc fd : c.enumConstants()) { + tableLine(Align.LEFT, fd.name()); + } + } + innerTableEnd(); + } + if (!c.isEnum() && (opt.showConstructors || opt.showOperations)) { + innerTableStart(); + boolean printedLines = false; + if (opt.showConstructors) + printedLines |= operations(opt, c.constructors()); + if (opt.showOperations) + printedLines |= operations(opt, c.methods()); - if (ci == null) - ci = newClassInfo(c, false, false); + if (!printedLines) + // if there are no operations nor constructors, + // print an empty line to generate proper HTML + tableLine(Align.LEFT, ""); + + innerTableEnd(); + } + } + externalTableEnd(); + if (url != null) + w.print(", URL=\"" + url + "\""); + nodeProperties(opt); + + // If needed, add a note for this node + int ni = 0; + for (Tag t : c.tags("note")) { + String noteName = "n" + ni + "c" + ci.name; + w.print(linePrefix + "// Note annotation\n"); + w.print(linePrefix + noteName + " [label="); + externalTableStart(UmlGraph.getCommentOptions(), c.qualifiedName(), url); + innerTableStart(); + tableLine(Align.LEFT, Font.CLASS.wrap(UmlGraph.getCommentOptions(), htmlNewline(escape(t.text())))); + innerTableEnd(); + externalTableEnd(); + nodeProperties(UmlGraph.getCommentOptions()); + ClassInfo ci1 = getClassInfo(c, true); + w.print(linePrefix + noteName + " -> " + ci1.name + "[arrowhead=none];\n"); + ni++; + } + ci.nodePrinted = true; return ci.name; } @@ -623,16 +493,15 @@ class ClassGraph { * @param edgetype the dot edge specification */ private void allRelation(Options opt, RelationType rt, ClassDoc from) { - String tagname = rt.toString().toLowerCase(); + String tagname = rt.lower; for (Tag tag : from.tags(tagname)) { - String t[] = StringUtil.tokenize(tag.text()); // l-src label l-dst target + String t[] = tokenize(tag.text()); // l-src label l-dst target + t = t.length == 1 ? new String[] { "-", "-", "-", t[0] } : t; // Shorthand if (t.length != 4) { System.err.println("Error in " + from + "\n" + tagname + " expects four fields (l-src label l-dst target): " + tag.text()); return; } ClassDoc to = from.findClass(t[3]); - - if (to != null) { if(hidden(to)) continue; @@ -654,27 +523,39 @@ class ClassGraph { */ private void relation(Options opt, RelationType rt, ClassDoc from, String fromName, ClassDoc to, String toName, String tailLabel, String label, String headLabel) { + tailLabel = (tailLabel != null && !tailLabel.isEmpty()) ? ",taillabel=\"" + tailLabel + "\"" : ""; + label = (label != null && !label.isEmpty()) ? ",label=\"" + guillemize(opt, label) + "\"" : ""; + headLabel = (headLabel != null && !headLabel.isEmpty()) ? ",headlabel=\"" + headLabel + "\"" : ""; + boolean unLabeled = tailLabel.isEmpty() && label.isEmpty() && headLabel.isEmpty(); + ClassInfo ci1 = getClassInfo(from, fromName, true), ci2 = getClassInfo(to, toName, true); + String n1 = ci1.name, n2 = ci2.name; + // For ranking we need to output extends/implements backwards. + if (rt.backorder) { // Swap: + n1 = ci2.name; + n2 = ci1.name; + String tmp = tailLabel; + tailLabel = headLabel; + headLabel = tmp; + } + Options def = opt.getGlobalOptions(); // print relation - String edgetype = associationMap.get(rt); - w.println("\t// " + fromName + " " + rt.toString() + " " + toName); - w.println("\t" + relationNode(from, fromName) + " -> " + relationNode(to, toName) + " [" + - "taillabel=\"" + tailLabel + "\", " + - ((label == null || label.isEmpty()) ? "label=\"\", " : "label=\"" + guillemize(opt, label) + "\", ") + - "headlabel=\"" + headLabel + "\", " + - "fontname=\"" + opt.edgeFontName + "\", " + - "fontcolor=\"" + opt.edgeFontColor + "\", " + - "fontsize=" + opt.edgeFontSize + ", " + - "color=\"" + opt.edgeColor + "\", " + - edgetype + "];" - ); + w.println(linePrefix + "// " + fromName + " " + rt.lower + " " + toName); + w.println(linePrefix + n1 + " -> " + n2 + " [" + rt.style + + (opt.edgeColor != def.edgeColor ? ",color=\"" + opt.edgeColor + "\"" : "") + + (unLabeled ? "" : + (opt.edgeFontName != def.edgeFontName ? ",fontname=\"" + opt.edgeFontName + "\"" : "") + + (opt.edgeFontColor != def.edgeFontColor ? ",fontcolor=\"" + opt.edgeFontColor + "\"" : "") + + (opt.edgeFontSize != def.edgeFontSize ? ",fontsize=" + fmt(opt.edgeFontSize) : "")) + + tailLabel + label + headLabel + + "];"); // update relation info RelationDirection d = RelationDirection.BOTH; if(rt == RelationType.NAVASSOC || rt == RelationType.DEPEND) d = RelationDirection.OUT; - getClassInfo(fromName).addRelation(toName, rt, d); - getClassInfo(toName).addRelation(fromName, rt, d.inverse()); + ci1.addRelation(toName, rt, d); + ci2.addRelation(fromName, rt, d.inverse()); } /** @@ -688,79 +569,33 @@ class ClassGraph { } - /** Return the full name of a relation's node. - * This may involve appending the port :p for the standard nodes - * whose outline is rendered through an inner table. - */ - private String relationNode(ClassDoc c) { - Options opt = optionProvider.getOptionsFor(c); - String name = getNodeName(c); - return name + opt.shape.landingPort(); - } - - /** Return the full name of a relation's node c. - * This may involve appending the port :p for the standard nodes - * whose outline is rendered through an inner table. - * @param c the node's class (may be null) - * @param cName the node's class name - */ - private String relationNode(ClassDoc c, String cName) { - Options opt; - if (c == null) - opt = optionProvider.getOptionsFor(cName); - else - opt = optionProvider.getOptionsFor(c); - String name = getNodeName(cName); - return name + opt.shape.landingPort(); - } - /** Print a class's relations */ public void printRelations(ClassDoc c) { Options opt = optionProvider.getOptionsFor(c); if (hidden(c) || c.name().equals("")) // avoid phantom classes, they may pop up when the source uses annotations return; - String className = c.toString(); - // Print generalization (through the Java superclass) Type s = c.superclassType(); - if (s != null && - !s.toString().equals("java.lang.Object") && - !c.isEnum() && - !hidden(s.asClassDoc())) { - ClassDoc sc = s.asClassDoc(); - w.println("\t//" + c + " extends " + s + "\n" + - "\t" + relationNode(sc) + " -> " + relationNode(c) + " [dir=back,arrowtail=empty];"); - getClassInfo(className).addRelation(sc.toString(), RelationType.EXTENDS, RelationDirection.OUT); - getClassInfo(sc.toString()).addRelation(className, RelationType.EXTENDS, RelationDirection.IN); - } - + ClassDoc sc = s != null && !s.qualifiedTypeName().equals(Object.class.getName()) ? s.asClassDoc() : null; + if (sc != null && !c.isEnum() && !hidden(sc)) + relation(opt, RelationType.EXTENDS, c, sc, null, null, null); // Print generalizations (through @extends tags) for (Tag tag : c.tags("extends")) - if (!hidden(tag.text())) { - ClassDoc from = c.findClass(tag.text()); - w.println("\t//" + c + " extends " + tag.text() + "\n" + - "\t" + relationNode(from, tag.text()) + " -> " + relationNode(c) + " [dir=back,arrowtail=empty];"); - getClassInfo(className).addRelation(tag.text(), RelationType.EXTENDS, RelationDirection.OUT); - getClassInfo(tag.text()).addRelation(className, RelationType.EXTENDS, RelationDirection.IN); - } + if (!hidden(tag.text())) + relation(opt, RelationType.EXTENDS, c, c.findClass(tag.text()), null, null, null); // Print realizations (Java interfaces) for (Type iface : c.interfaceTypes()) { ClassDoc ic = iface.asClassDoc(); - if (!hidden(ic)) { - w.println("\t//" + c + " implements " + ic + "\n\t" + - relationNode(ic) + " -> " + relationNode(c) + " [dir=back,arrowtail=empty,style=dashed];" - ); - getClassInfo(className).addRelation(ic.toString(), RelationType.IMPLEMENTS, RelationDirection.OUT); - getClassInfo(ic.toString()).addRelation(className, RelationType.IMPLEMENTS, RelationDirection.IN); - } + if (!hidden(ic)) + relation(opt, RelationType.IMPLEMENTS, c, ic, null, null, null); } // Print other associations - allRelation(opt, RelationType.ASSOC, c); - allRelation(opt, RelationType.NAVASSOC, c); - allRelation(opt, RelationType.HAS, c); - allRelation(opt, RelationType.NAVHAS, c); allRelation(opt, RelationType.COMPOSED, c); allRelation(opt, RelationType.NAVCOMPOSED, c); + allRelation(opt, RelationType.HAS, c); + allRelation(opt, RelationType.NAVHAS, c); + allRelation(opt, RelationType.ASSOC, c); + allRelation(opt, RelationType.NAVASSOC, c); allRelation(opt, RelationType.DEPEND, c); } @@ -768,80 +603,69 @@ class ClassGraph { public void printExtraClasses(RootDoc root) { Set names = new HashSet(classnames.keySet()); for(String className: names) { - ClassInfo info = getClassInfo(className); - if (!info.nodePrinted) { - ClassDoc c = root.classNamed(className); - if(c != null) { - printClass(c, false); - } else { - Options opt = optionProvider.getOptionsFor(className); - if(opt.matchesHideExpression(className)) - continue; - w.println("\t// " + className); - w.print("\t" + info.name + "[label="); - externalTableStart(opt, className, classToUrl(className)); - innerTableStart(); - int idx = className.lastIndexOf("."); - if(opt.postfixPackage && idx > 0 && idx < (className.length() - 1)) { - String packageName = className.substring(0, idx); - String cn = className.substring(idx + 1); - tableLine(Align.CENTER, escape(cn), opt, Font.CLASS); - tableLine(Align.CENTER, packageName, opt, Font.PACKAGE); - } else { - tableLine(Align.CENTER, escape(className), opt, Font.CLASS); - } - innerTableEnd(); - externalTableEnd(); - if (className == null || className.length() == 0) - w.print(", URL=\"" + classToUrl(className) + "\""); - nodeProperties(opt); - } + ClassInfo info = getClassInfo(className, true); + if (info.nodePrinted) + continue; + ClassDoc c = root.classNamed(className); + if(c != null) { + printClass(c, false); + continue; } + // Handle missing classes: + Options opt = optionProvider.getOptionsFor(className); + if(opt.matchesHideExpression(className)) + continue; + w.println(linePrefix + "// " + className); + w.print(linePrefix + info.name + "[label="); + externalTableStart(opt, className, classToUrl(className)); + innerTableStart(); + String qualifiedName = qualifiedName(opt, className); + int startTemplate = qualifiedName.indexOf('<'); + int idx = qualifiedName.lastIndexOf('.', startTemplate < 0 ? qualifiedName.length() - 1 : startTemplate); + if(opt.postfixPackage && idx > 0 && idx < (qualifiedName.length() - 1)) { + String packageName = qualifiedName.substring(0, idx); + String cn = qualifiedName.substring(idx + 1); + tableLine(Align.CENTER, Font.CLASS.wrap(opt, escape(cn))); + tableLine(Align.CENTER, Font.PACKAGE.wrap(opt, packageName)); + } else { + tableLine(Align.CENTER, Font.CLASS.wrap(opt, escape(qualifiedName))); + } + innerTableEnd(); + externalTableEnd(); + if (className == null || className.length() == 0) + w.print(",URL=\"" + classToUrl(className) + "\""); + nodeProperties(opt); } } - /** - * Prints associations recovered from the fields of a class. An association is inferred only - * if another relation between the two classes is not already in the graph. - * @param classes - */ - public void printInferredRelations(ClassDoc[] classes) { - for (ClassDoc c : classes) { - printInferredRelations(c); - } - } - /** * Prints associations recovered from the fields of a class. An association is inferred only * if another relation between the two classes is not already in the graph. * @param classes */ public void printInferredRelations(ClassDoc c) { - Options opt = optionProvider.getOptionsFor(c); - // check if the source is excluded from inference if (hidden(c)) return; + Options opt = optionProvider.getOptionsFor(c); + for (FieldDoc field : c.fields(false)) { if(hidden(field)) continue; - // skip statics if(field.isStatic()) continue; - // skip primitives FieldRelationInfo fri = getFieldRelationInfo(field); if (fri == null) continue; - // check if the destination is excluded from inference if (hidden(fri.cd)) continue; // if source and dest are not already linked, add a dependency - RelationPattern rp = getClassInfo(c.toString()).getRelation(fri.cd.toString()); + RelationPattern rp = getClassInfo(c, true).getRelation(fri.cd.toString()); if (rp == null) { String destAdornment = fri.multiple ? "*" : ""; relation(opt, opt.inferRelationshipType, c, fri.cd, "", "", destAdornment); @@ -849,18 +673,6 @@ class ClassGraph { } } - /** - * Prints dependencies recovered from the methods of a class. A - * dependency is inferred only if another relation between the two - * classes is not already in the graph. - * @param classes - */ - public void printInferredDependencies(ClassDoc[] classes) { - for (ClassDoc c : classes) { - printInferredDependencies(c); - } - } - /** Returns an array representing the imported classes of c. * Disables the deprecation warning, which is output, because the * imported classed are an implementation detail. @@ -877,12 +689,10 @@ class ClassGraph { * @param classes */ public void printInferredDependencies(ClassDoc c) { - Options opt = optionProvider.getOptionsFor(c); - - String sourceName = c.toString(); if (hidden(c)) return; + Options opt = optionProvider.getOptionsFor(c); Set types = new HashSet(); // harvest method return and parameter types for (MethodDoc method : filterByVisibility(c.methods(false), opt.inferDependencyVisibility)) { @@ -932,7 +742,7 @@ class ClassGraph { continue; // if source and dest are not already linked, add a dependency - RelationPattern rp = getClassInfo(sourceName).getRelation(fc.toString()); + RelationPattern rp = getClassInfo(c, true).getRelation(fc.toString()); if (rp == null || rp.matchesOne(new RelationPattern(RelationDirection.OUT))) { relation(opt, RelationType.DEPEND, c, fc, "", "", ""); } @@ -1008,127 +818,48 @@ class ClassGraph { return null; } - /** Removes the template specs from a class name. */ - private String removeTemplate(String name) { - int openIdx = name.indexOf('<'); - if(openIdx == -1) - return name; - else - return name.substring(0, openIdx); - } - /** Convert the class name into a corresponding URL */ public String classToUrl(ClassDoc cd, boolean rootClass) { // building relative path for context and package diagrams - if(contextDoc != null && rootClass) { - // determine the context path, relative to the root - String packageName = null; - if (contextDoc instanceof ClassDoc) { - packageName = ((ClassDoc) contextDoc).containingPackage().name(); - } else if (contextDoc instanceof PackageDoc) { - packageName = ((PackageDoc) contextDoc).name(); - } else { - return classToUrl(cd.qualifiedName()); - } - return buildRelativePath(packageName, cd.containingPackage().name()) + cd.name() + ".html"; - } else { - return classToUrl(cd.qualifiedName()); - } + if(contextPackageName != null && rootClass) + return buildRelativePathFromClassNames(contextPackageName, cd.containingPackage().name()) + cd.name() + ".html"; + return classToUrl(cd.qualifiedName()); } - protected static String buildRelativePath(String contextPackageName, String classPackageName) { - // path, relative to the root, of the destination class - String[] contextClassPath = contextPackageName.split("\\."); - String[] currClassPath = classPackageName.split("\\."); - - // compute relative path between the context and the destination - // ... first, compute common part - int i = 0; - while (i < contextClassPath.length && i < currClassPath.length - && contextClassPath[i].equals(currClassPath[i])) - i++; - // ... go up with ".." to reach the common root - StringBuffer buf = new StringBuffer(); - if (i == contextClassPath.length) { - buf.append(".").append(FILE_SEPARATOR); - } else { - for (int j = i; j < contextClassPath.length; j++) { - buf.append("..").append(FILE_SEPARATOR); - } - } - // ... go down from the common root to the destination - for (int j = i; j < currClassPath.length; j++) { - buf.append(currClassPath[j]).append(FILE_SEPARATOR); - } - return buf.toString(); - } - - private String getPackageName(String className) { - if (this.rootClassdocs.get(className) == null) { - int idx = className.lastIndexOf('.'); - return idx > 0 ? className.substring(0, idx) : ""; - } else { - return this.rootClassdocs.get(className).containingPackage().name(); - } - } - - private String getUnqualifiedName(String className) { - if (this.rootClassdocs.get(className) == null) { - int idx = className.lastIndexOf('.'); - return idx > 0 ? className.substring(idx + 1) : className; - } else { - return this.rootClassdocs.get(className).name(); - } - } - /** Convert the class name into a corresponding URL */ public String classToUrl(String className) { - String docRoot = mapApiDocRoot(className); - if (docRoot != null) { - StringBuffer buf = new StringBuffer(docRoot); - buf.append(getPackageName(className).replace('.', FILE_SEPARATOR) + FILE_SEPARATOR); - buf.append(getUnqualifiedName(className)); - buf.append(".html"); - return buf.toString(); - } else { - return null; - } - } - - /** - * Returns the appropriate URL "root" for a given class name. - * The root will be used as the prefix of the URL used to link the class in - * the final diagram to the associated JavaDoc page. - */ - private String mapApiDocRoot(String className) { - String root = null; - /* If no packages are specified, we use apiDocRoot for all of them. */ - if (rootClasses.contains(className)) { - root = optionProvider.getGlobalOptions().apiDocRoot; - } else { - Options globalOptions = optionProvider.getGlobalOptions(); - root = globalOptions.getApiDocRoot(className); + ClassDoc classDoc = rootClassdocs.get(className); + if (classDoc != null) { + String docRoot = optionProvider.getGlobalOptions().apiDocRoot; + if (docRoot == null) + return null; + return new StringBuilder(docRoot.length() + className.length() + 10).append(docRoot) // + .append(classDoc.containingPackage().name().replace('.', '/')) // + .append('/').append(classDoc.name()).append(".html").toString(); } - return root; + String docRoot = optionProvider.getGlobalOptions().getApiDocRoot(className); + if (docRoot == null) + return null; + int split = splitPackageClass(className); + StringBuilder buf = new StringBuilder(docRoot.length() + className.length() + 10).append(docRoot); + if (split > 0) // Avoid -1, and the extra slash then. + buf.append(className.substring(0, split).replace('.', '/')).append('/'); + return buf.append(className, Math.min(split + 1, className.length()), className.length()) // + .append(".html").toString(); } - /** Dot prologue * @throws IOException */ public void prologue() throws IOException { Options opt = optionProvider.getGlobalOptions(); - OutputStream os = null; + OutputStream os; if (opt.outputFileName.equals("-")) os = System.out; else { // prepare output file. Use the output file name as a full path unless the output // directory is specified - File file = null; - if (opt.outputDirectory != null) - file = new File(opt.outputDirectory, opt.outputFileName); - else - file = new File(opt.outputFileName); + File file = new File(opt.outputDirectory, opt.outputFileName); // make sure the output directory are there, otherwise create them if (file.getParentFile() != null && !file.getParentFile().exists()) @@ -1143,22 +874,27 @@ class ClassGraph { "#\n" + "# Class diagram \n" + "# Generated by UMLGraph version " + - Version.VERSION + " (http://www.umlgraph.org/)\n" + + Version.VERSION + " (http://www.spinellis.gr/umlgraph/)\n" + "#\n\n" + "digraph G {\n" + - "\tedge [fontname=\"" + opt.edgeFontName + - "\",fontsize=10,labelfontname=\"" + opt.edgeFontName + - "\",labelfontsize=10];\n" + - "\tnode [fontname=\"" + opt.nodeFontName + - "\",fontsize=10,shape=plaintext];" + linePrefix + "graph [fontnames=\"svg\"]\n" + + linePrefix + "edge [fontname=\"" + opt.edgeFontName + + "\",fontsize=" + fmt(opt.edgeFontSize) + + ",labelfontname=\"" + opt.edgeFontName + + "\",labelfontsize=" + fmt(opt.edgeFontSize) + + ",color=\"" + opt.edgeColor + "\"];\n" + + linePrefix + "node [fontname=\"" + opt.nodeFontName + + "\",fontcolor=\"" + opt.nodeFontColor + + "\",fontsize=" + fmt(opt.nodeFontSize) + + ",shape=plaintext,margin=0,width=0,height=0];" ); - w.println("\tnodesep=" + opt.nodeSep + ";"); - w.println("\tranksep=" + opt.rankSep + ";"); + w.println(linePrefix + "nodesep=" + opt.nodeSep + ";"); + w.println(linePrefix + "ranksep=" + opt.rankSep + ";"); if (opt.horizontal) - w.println("\trankdir=LR;"); + w.println(linePrefix + "rankdir=LR;"); if (opt.bgColor != null) - w.println("\tbgcolor=\"" + opt.bgColor + "\";\n"); + w.println(linePrefix + "bgcolor=\"" + opt.bgColor + "\";\n"); } /** Dot epilogue */ @@ -1169,16 +905,11 @@ class ClassGraph { } private void externalTableStart(Options opt, String name, String url) { - String bgcolor = ""; - if (opt.nodeFillColor != null) - bgcolor = " bgcolor=\""+ opt.nodeFillColor + "\""; - String href = ""; - if (url != null) - href = " href=\"" + url + "\" target=\"_parent\""; - + String bgcolor = opt.nodeFillColor == null ? "" : (" bgcolor=\"" + opt.nodeFillColor + "\""); + String href = url == null ? "" : (" href=\"" + url + "\" target=\"_parent\""); w.print("<" + linePostfix); + "cellpadding=\"2\"" + bgcolor + href + ">" + linePostfix); } private void externalTableEnd() { @@ -1192,10 +923,9 @@ class ClassGraph { /** * Start the first inner table of a class. - * @param nRows the total number of rows in this table. */ - private void firstInnerTableStart(Options opt, int nRows) { - w.print(linePrefix + linePrefix + "" + opt.shape.extraColumn(nRows) + + private void firstInnerTableStart(Options opt) { + w.print(linePrefix + linePrefix + "" + opt.shape.extraColumn() + "" + - opt.shape.extraColumn(nRows) + "" + linePostfix); + opt.shape.extraColumn() + "" + linePostfix); } private void tableLine(Align align, String text) { - tableLine(align, text, null, Font.NORMAL); + w.print(linePrefix + linePrefix // + + "" + linePostfix); } - - private void tableLine(Align align, String text, Options opt, Font font) { - String open; - String close = ""; - String prefix = linePrefix + linePrefix + linePrefix; - String alignText; - if(align == Align.CENTER) - alignText = "center"; - else if(align == Align.LEFT) - alignText = "left"; - else if(align == Align.RIGHT) - alignText = "right"; - else - throw new RuntimeException("Unknown alignement type " + align); - - text = fontWrap(" " + text + " ", opt, font); - open = "") : ""; + public String extraColumn() { + return this == Shape.ACTIVECLASS ? ("") : ""; } /** Return the cell border required for the shape */ - String cellBorder() { - return (name.equals("class") || name.equals("activeclass")) ? "1" : "0"; + public String cellBorder() { + return this == CLASS || this == ACTIVECLASS ? "1" : "0"; } } diff --git a/src/main/java/org/umlgraph/doclet/StringUtil.java b/src/main/java/org/umlgraph/doclet/StringUtil.java index 2aa9eac..e122e0b 100644 --- a/src/main/java/org/umlgraph/doclet/StringUtil.java +++ b/src/main/java/org/umlgraph/doclet/StringUtil.java @@ -20,9 +20,11 @@ package org.umlgraph.doclet; import java.util.*; +import java.util.regex.Pattern; /** * String utility functions + * * @version $Revision$ * @author Diomidis Spinellis */ @@ -62,4 +64,168 @@ class StringUtil { return r.toArray(new String[0]); } + private final static Pattern ESCAPE_BASIC_XML = Pattern.compile("[&<>]"); + + /** + * Escape <, >, and & characters in the string with the corresponding + * HTML entity code. + */ + public static String escape(String s) { + if (ESCAPE_BASIC_XML.matcher(s).find()) { + StringBuilder sb = new StringBuilder(s); + for (int i = 0; i < sb.length();) { + switch (sb.charAt(i)) { + case '&': + sb.replace(i, i + 1, "&"); + i += "&".length(); + break; + case '<': + sb.replace(i, i + 1, "<"); + i += "<".length(); + break; + case '>': + sb.replace(i, i + 1, ">"); + i += ">".length(); + break; + default: + i++; + } + } + return sb.toString(); + } else + return s; + } + + /** + * Convert embedded newlines into HTML line breaks + */ + public static String htmlNewline(String s) { + if (s.indexOf('\n') == -1) + return s; + + StringBuilder sb = new StringBuilder(s); + for (int i = 0; i < sb.length();) { + if (sb.charAt(i) == '\n') { + sb.replace(i, i + 1, "
    "); + i += "
    ".length(); + } else + i++; + } + return sb.toString(); + } + + /** + * Convert < and > characters in the string to the respective guillemot + * characters. + */ + public static String guillemize(Options opt, String s) { + StringBuilder r = new StringBuilder(s); + for (int i = 0; i < r.length();) + switch (r.charAt(i)) { + case '<': + r.replace(i, i + 1, opt.guilOpen); + i += opt.guilOpen.length(); + break; + case '>': + r.replace(i, i + 1, opt.guilClose); + i += opt.guilClose.length(); + break; + default: + i++; + break; + } + return r.toString(); + } + + /** + * Wraps a string in Guillemot (or an ASCII substitute) characters. + * + * @param str the String to be wrapped. + * @return the wrapped String. + */ + public static String guilWrap(Options opt, String str) { + return opt.guilOpen + str + opt.guilClose; + } + + /** Removes the template specs from a class name. */ + public static String removeTemplate(String name) { + int openIdx = name.indexOf('<'); + if (openIdx == -1) + return name; + StringBuilder buf = new StringBuilder(name.length()); + for (int i = 0, depth = 0; i < name.length(); i++) { + char c = name.charAt(i); + if (c == '<') + depth++; + else if (c == '>') + depth--; + else if (depth == 0) + buf.append(c); + } + return buf.toString(); + } + + public static String buildRelativePathFromClassNames(String contextPackageName, String classPackageName) { + // path, relative to the root, of the destination class + String[] contextClassPath = contextPackageName.split("\\."); + String[] currClassPath = classPackageName.split("\\."); + + // compute relative path between the context and the destination + // ... first, compute common part + int i = 0, e = Math.min(contextClassPath.length, currClassPath.length); + while (i < e && contextClassPath[i].equals(currClassPath[i])) + i++; + // ... go up with ".." to reach the common root + StringBuilder buf = new StringBuilder(classPackageName.length()); + for (int j = i; j < contextClassPath.length; j++) + buf.append("../"); + // ... go down from the common root to the destination + for (int j = i; j < currClassPath.length; j++) + buf.append(currClassPath[j]).append('/'); // Always use HTML seperators + return buf.toString(); + } + + /** + * We can't just always use the last dot, because there are inner classes. And + * these may have frequent names. But the prime example is + * {@link java.util.Map.Entry}, which we want to show up as package + * java.util and class Map.Entry. + *

    + * Note: this is only a heuristic. We only have the string here, and must assume + * users adhere to Java conventions, of beginning package names with a lowercase + * letter. + * + * @param className + * @return Splitting point (Either referring to a dot, or -1) + */ + public static int splitPackageClass(String className) { + int gen = className.indexOf('<'); // Begin before generics. + int end = gen >= 0 ? gen : className.length(); + int start = className.lastIndexOf('.', end); + // No package name special cases: + if (start < 0) + return gen >= 0 || className.isEmpty() ? -1 // + : Character.isLowerCase(className.charAt(0)) ? end : -1; + int split = end; + while (true) { + if (Character.isLowerCase(className.charAt(start + 1))) + return split; + split = start; // Continue, this looks like a class name. + if (start < 0) + return -1; + start = className.lastIndexOf('.', start - 1); + } + } + + /** + * Format a double to a string. + *

    + * Avoids printing "10.0" for exact values like 10. + * + * @param val Value + * @return Formatted value + */ + public static String fmt(double val) { + return val == Math.round(val) ? Long.toString((long) val) : Double.toString(val); + } } diff --git a/src/main/java/org/umlgraph/doclet/SubclassMatcher.java b/src/main/java/org/umlgraph/doclet/SubclassMatcher.java index 0588eda..999b823 100644 --- a/src/main/java/org/umlgraph/doclet/SubclassMatcher.java +++ b/src/main/java/org/umlgraph/doclet/SubclassMatcher.java @@ -25,17 +25,12 @@ public class SubclassMatcher implements ClassMatcher { return true; // recurse on supeclass, if available - if(cd.superclass() != null) - return matches(cd.superclass()); - - return false; + return cd.superclass() == null ? false : matches(cd.superclass()); } public boolean matches(String name) { ClassDoc cd = root.classNamed(name); - if(cd == null) - return false; - return matches(cd); + return cd == null ? false : matches(cd); } } diff --git a/src/main/java/org/umlgraph/doclet/UmlGraph.java b/src/main/java/org/umlgraph/doclet/UmlGraph.java index 7087772..edd3825 100644 --- a/src/main/java/org/umlgraph/doclet/UmlGraph.java +++ b/src/main/java/org/umlgraph/doclet/UmlGraph.java @@ -84,7 +84,7 @@ public class UmlGraph { commentOptions = new Options(); commentOptions.setOptions(root.options()); commentOptions.setOptions(findClass(root, "UMLNoteOptions")); - commentOptions.shape = new Shape("note"); + commentOptions.shape = Shape.NOTE; Options opt = new Options(); opt.setOptions(root.options()); @@ -113,14 +113,16 @@ public class UmlGraph { 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]); + for (ClassDoc cd : classes) + c.printClass(cd, true); + for (ClassDoc cd : classes) + c.printRelations(cd); if(opt.inferRelationships) - c.printInferredRelations(classes); + for (ClassDoc cd : classes) + c.printInferredRelations(cd); if(opt.inferDependencies) - c.printInferredDependencies(classes); + for (ClassDoc cd : classes) + c.printInferredDependencies(cd); c.printExtraClasses(root); c.epilogue(); diff --git a/src/main/java/org/umlgraph/doclet/UmlGraphDoc.java b/src/main/java/org/umlgraph/doclet/UmlGraphDoc.java index 6dda3a2..dca406f 100644 --- a/src/main/java/org/umlgraph/doclet/UmlGraphDoc.java +++ b/src/main/java/org/umlgraph/doclet/UmlGraphDoc.java @@ -62,12 +62,10 @@ public class UmlGraphDoc { 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()); + root.printWarning("Error: " + t.toString()); t.printStackTrace(); return false; } @@ -117,14 +115,18 @@ public class UmlGraphDoc { ContextView view = null; for (ClassDoc classDoc : classDocs) { - if(view == null) - view = new ContextView(outputFolder, classDoc, root, opt); - else - view.setContextCenter(classDoc); - UmlGraph.buildGraph(root, view, classDoc); - runGraphviz(opt.dotExecutable, outputFolder, classDoc.containingPackage().name(), classDoc.name(), root); - alterHtmlDocs(opt, outputFolder, classDoc.containingPackage().name(), classDoc.name(), - classDoc.name() + ".html", Pattern.compile(".*(Class|Interface|Enum) " + classDoc.name() + ".*") , root); + try { + if(view == null) + view = new ContextView(outputFolder, classDoc, root, opt); + else + view.setContextCenter(classDoc); + UmlGraph.buildGraph(root, view, classDoc); + runGraphviz(opt.dotExecutable, outputFolder, classDoc.containingPackage().name(), classDoc.name(), root); + alterHtmlDocs(opt, outputFolder, classDoc.containingPackage().name(), classDoc.name(), + classDoc.name() + ".html", Pattern.compile(".*(Class|Interface|Enum) " + classDoc.name() + ".*") , root); + } catch (Exception e) { + throw new RuntimeException("Error generating " + classDoc.name(), e); + } } } @@ -147,7 +149,7 @@ public class UmlGraphDoc { dotFile.getAbsolutePath() }); BufferedReader reader = new BufferedReader(new InputStreamReader(p.getErrorStream())); - String line = null; + String line; while((line = reader.readLine()) != null) root.printWarning(line); int result = p.waitFor(); @@ -162,9 +164,14 @@ public class UmlGraphDoc { //Format string for the uml image div tag. private static final String UML_DIV_TAG = "

    " + - "" + + "" + "
    "; + private static final String UML_AUTO_SIZED_DIV_TAG = + "
    " + + "" + + "
    "; + private static final String EXPANDABLE_UML_STYLE = "font-family: Arial,Helvetica,sans-serif;font-size: 1.5em; display: block; width: 250px; height: 20px; background: #009933; padding: 5px; text-align: center; border-radius: 8px; color: white; font-weight: bold;"; //Format string for the java script tag. @@ -217,12 +224,16 @@ public class UmlGraphDoc { if (!matched && insertPointPattern.matcher(line).matches()) { matched = true; - String tag = String.format(UML_DIV_TAG, className); + String tag; + if (opt.autoSize) + tag = String.format(UML_AUTO_SIZED_DIV_TAG, className); + else + tag = String.format(UML_DIV_TAG, className); if (opt.collapsibleDiagrams) tag = String.format(EXPANDABLE_UML, tag, "Show UML class diagram", "Hide UML class diagram"); writer.write(""); + " (http://www.spinellis.gr/umlgraph/) -->"); writer.newLine(); writer.write(tag); writer.newLine(); diff --git a/src/main/java/org/umlgraph/doclet/Version.java b/src/main/java/org/umlgraph/doclet/Version.java index 3a25f61..03f857d 100644 --- a/src/main/java/org/umlgraph/doclet/Version.java +++ b/src/main/java/org/umlgraph/doclet/Version.java @@ -1,4 +1,4 @@ /* Automatically generated file */ package org.umlgraph.doclet; -class Version { public static String VERSION = "R5_7_2-1-g9039a0";} +class Version { public static String VERSION = "R5_7_2-60-g0e99a6";} \ No newline at end of file diff --git a/src/main/java/org/umlgraph/doclet/View.java b/src/main/java/org/umlgraph/doclet/View.java index 808afd7..8659a1c 100644 --- a/src/main/java/org/umlgraph/doclet/View.java +++ b/src/main/java/org/umlgraph/doclet/View.java @@ -140,36 +140,30 @@ public class View implements OptionProvider { boolean outputSet = false; for (String[] opts : globalOptions) { - if (opts[0].equals("-output")) + if (Options.matchOption(opts[0], "output")) outputSet = true; go.setOption(opts); } if (!outputSet) - go.setOption(new String[] { "-output", viewDoc.name() + ".dot" }); + 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)) { + 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)) { + for (ClassMatcher cm : optionOverrides.keySet()) + if(cm.matches(className)) + for (String[] override : optionOverrides.get(cm)) opt.setOption(override); - } - } - } } public String getDisplayName() { diff --git a/src/main/java/org/umlgraph/doclet/Visibility.java b/src/main/java/org/umlgraph/doclet/Visibility.java index 0e631f6..408a551 100644 --- a/src/main/java/org/umlgraph/doclet/Visibility.java +++ b/src/main/java/org/umlgraph/doclet/Visibility.java @@ -24,10 +24,15 @@ 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; + PRIVATE("- "), PACKAGE("~ "), PROTECTED("# "), PUBLIC("+ "); + + final public String symbol; + + private Visibility(String symbol) { + this.symbol = symbol; + } public static Visibility get(ProgramElementDoc doc) { if (doc.isPrivate()) @@ -38,6 +43,5 @@ public enum Visibility { return PROTECTED; else return PUBLIC; - } -} \ No newline at end of file +} diff --git a/src/main/java/org/umlgraph/doclet/WrappedClassDoc.java b/src/main/java/org/umlgraph/doclet/WrappedClassDoc.java deleted file mode 100644 index 081e458..0000000 --- a/src/main/java/org/umlgraph/doclet/WrappedClassDoc.java +++ /dev/null @@ -1,369 +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. - * - * - */ - -package org.umlgraph.doclet; - -import com.sun.javadoc.AnnotatedType; -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). - *

    - * 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. - *

    - * 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(); - } - - public AnnotatedType asAnnotatedType() { - return wrapped.asAnnotatedType(); - } - - public Type getElementType() { - return wrapped.getElementType(); - } -} diff --git a/src/main/java/org/umlgraph/doclet/WrappedRootDoc.java b/src/main/java/org/umlgraph/doclet/WrappedRootDoc.java deleted file mode 100644 index 0bfc396..0000000 --- a/src/main/java/org/umlgraph/doclet/WrappedRootDoc.java +++ /dev/null @@ -1,191 +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. - * - * - */ - -package org.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); - } - -} diff --git a/src/test/java/org/umlgraph/test/BasicTest.java b/src/test/java/org/umlgraph/test/BasicTest.java index 7ceeae0..28f1cad 100644 --- a/src/test/java/org/umlgraph/test/BasicTest.java +++ b/src/test/java/org/umlgraph/test/BasicTest.java @@ -50,9 +50,6 @@ public class BasicTest { TestUtils.cleanFolder(outFolder, true); - // don't use windows specific fonts - System.setProperty("os.name", "generic"); - // run tests performBasicTests(differences); performViewTests(differences, outFolder); @@ -67,6 +64,7 @@ public class BasicTest { pw.println(); pw.println(); pw.flush(); + System.exit(differences.size() > 0 ? 1 : 0); } private static void performViewTests(List differences, File outFolder) diff --git a/src/test/java/org/umlgraph/test/DotDiff.java b/src/test/java/org/umlgraph/test/DotDiff.java index 32ae72a..266981a 100644 --- a/src/test/java/org/umlgraph/test/DotDiff.java +++ b/src/test/java/org/umlgraph/test/DotDiff.java @@ -166,16 +166,15 @@ public class DotDiff { int closedBracketIdx = line.lastIndexOf(']'); int arrowIdx = line.indexOf("->"); if (openBrackedIdx < 0 && closedBracketIdx < 0 || line.startsWith("edge") - || line.startsWith("node")) + || line.startsWith("node") || line.startsWith("graph")) 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 attMap = parseAttributes(attributes); - String name = line.substring(0, openBrackedIdx - 1).trim(); - String label = attMap.get("label"); - DotNode node = new DotNode(name, label, attMap, line); + String name = trim(line.substring(0, openBrackedIdx - 1)); + DotNode node = new DotNode(name, attMap.get("label"), attMap, line); nodes.put(name, node); nodeList.add(node); } @@ -185,19 +184,21 @@ public class DotDiff { 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(), ""); - } - if (to == null) { - to = new DotNode(names[1], "", new HashMap(), ""); - } + DotNode from = nodes.get(names[0] = trim(names[0])); + DotNode to = nodes.get(names[1] = trim(names[1])); + from = from != null ? from : new DotNode(names[0], "", new HashMap(), ""); + to = to != null? to : new DotNode(names[1], "", new HashMap(), ""); arcs.add(new DotArc(from, to, parseAttributes(attributes), line)); } return extraLines; } + // Trim space AND port. + private String trim(String name) { + name = name.trim(); + return name.endsWith(":p") ? name.substring(0, name.length() - 2) : name; + } + private Map parseAttributes(String attributes) throws IOException { Map map = new HashMap(); diff --git a/src/test/java/org/umlgraph/test/UmlDocTest.java b/src/test/java/org/umlgraph/test/UmlDocTest.java index c5a2c5f..d470b4f 100644 --- a/src/test/java/org/umlgraph/test/UmlDocTest.java +++ b/src/test/java/org/umlgraph/test/UmlDocTest.java @@ -50,9 +50,6 @@ public class UmlDocTest { TestUtils.cleanFolder(outFolder, true); - // don't use windows specific fonts - System.setProperty("os.name", "generic"); - // run tests runTest(differences); if (differences.size() > 0) { @@ -60,6 +57,7 @@ public class UmlDocTest { for (String className : differences) { pw.println(className); } + System.exit(1); } else { pw.println("GOOD, all files are structurally equal"); } @@ -150,10 +148,11 @@ public class UmlDocTest { private static void runDoclet(String[] options) { pw.print("Run javadoc -doclet " + doclet); for (String o : options) - pw.print(o + " "); + pw.print(" " + o); pw.println(); com.sun.tools.javadoc.Main.execute("UMLDoc test", pw, pw, pw, doclet, options); + System.exit(0); } } diff --git a/testdata/dot-ref/.gitignore b/testdata/dot-ref/.gitignore index b38f805..e33609d 100644 --- a/testdata/dot-ref/.gitignore +++ b/testdata/dot-ref/.gitignore @@ -1,2 +1 @@ -*.dot *.png diff --git a/testdata/dot-ref/Abstr.dot b/testdata/dot-ref/Abstr.dot index 708dba4..1528241 100644 --- a/testdata/dot-ref/Abstr.dot +++ b/testdata/dot-ref/Abstr.dot @@ -5,21 +5,22 @@ # digraph G { - edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; - node [fontname="Helvetica",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - // test.AbstractNode - c1 [label=<

    " + linePostfix); } @@ -1206,83 +936,19 @@ class ClassGraph { /** * End the first inner table of a class. - * @param nRows the total number of rows in this table. */ - private void firstInnerTableEnd(Options opt, int nRows) { + private void firstInnerTableEnd(Options opt) { w.print(linePrefix + linePrefix + "
    " // + + text // MAY contain markup! + + "
    "; - w.print(open + text + close + linePostfix); - } - - /** - * Wraps the text with the appropriate font according to the specified font type - * @param opt - * @param text - * @param font - * @return - */ - private String fontWrap(String text, Options opt, Font font) { - if(font == Font.ABSTRACT) { - return fontWrap(text, opt.nodeFontAbstractName, opt.nodeFontSize); - } else if(font == Font.CLASS) { - return fontWrap(text, opt.nodeFontClassName, opt.nodeFontClassSize); - } else if(font == Font.CLASS_ABSTRACT) { - String name; - if(opt.nodeFontClassAbstractName == null) - name = opt.nodeFontAbstractName; - else - name = opt.nodeFontClassAbstractName; - return fontWrap(text, name, opt.nodeFontClassSize); - } else if(font == Font.PACKAGE) { - return fontWrap(text, opt.nodeFontPackageName, opt.nodeFontPackageSize); - } else if(font == Font.TAG) { - return fontWrap(text, opt.nodeFontTagName, opt.nodeFontTagSize); - } else { - return text; - } - } - - /** - * Wraps the text with the appropriate font tags when the font name - * and size are not void - * @param text the text to be wrapped - * @param fontName considered void when it's null - * @param fontSize considered void when it's <= 0 - */ - private String fontWrap(String text, String fontName, double fontSize) { - if(fontName == null && fontSize == -1) - return text; - else if(fontName == null) - return "" + text + ""; - else if(fontSize <= 0) - return "" + text + ""; - else - return "" + text + ""; - } - private static class FieldRelationInfo { ClassDoc cd; boolean multiple; diff --git a/src/main/java/org/umlgraph/doclet/ClassInfo.java b/src/main/java/org/umlgraph/doclet/ClassInfo.java index 75727cf..f498210 100644 --- a/src/main/java/org/umlgraph/doclet/ClassInfo.java +++ b/src/main/java/org/umlgraph/doclet/ClassInfo.java @@ -20,7 +20,6 @@ package org.umlgraph.doclet; import java.util.HashMap; -import java.util.List; import java.util.Map; /** @@ -32,7 +31,7 @@ import java.util.Map; class ClassInfo { private static int classNumber; /** Alias name for the class */ - String name; + final String name; /** True if the class class node has been printed */ boolean nodePrinted; /** True if the class class node is hidden */ @@ -44,10 +43,9 @@ class ClassInfo { */ Map relatedClasses = new HashMap(); - ClassInfo(boolean p, boolean h) { - nodePrinted = p; + ClassInfo(boolean h) { hidden = h; - name = "c" + (new Integer(classNumber)).toString(); + name = "c" + classNumber; classNumber++; } diff --git a/src/main/java/org/umlgraph/doclet/ContextMatcher.java b/src/main/java/org/umlgraph/doclet/ContextMatcher.java index 47895af..cc59d00 100644 --- a/src/main/java/org/umlgraph/doclet/ContextMatcher.java +++ b/src/main/java/org/umlgraph/doclet/ContextMatcher.java @@ -67,9 +67,9 @@ public class ContextMatcher implements ClassMatcher { 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" }); + opt.setOption(new String[] { "!hide" }); + opt.setOption(new String[] { "!attributes" }); + opt.setOption(new String[] { "!operations" }); this.cg = new ClassGraphHack(root, opt); setContextCenter(pattern); @@ -97,26 +97,23 @@ public class ContextMatcher implements ClassMatcher { /** * Adds the specified class to the internal class graph along with its - * relations and depencies, eventually inferring them, according to the + * relations and dependencies, 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 + // 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) { + if (opt.inferRelationships) cg.printInferredRelations(cd); - } - if (opt.inferDependencies) { + if (opt.inferDependencies) cg.printInferredDependencies(cd); - } } /** @@ -144,10 +141,8 @@ public class ContextMatcher implements ClassMatcher { 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)) + RelationPattern rp = cg.getClassInfo(mcd, true).getRelation(name); + if (rp != null && opt.contextRelationPattern.matchesOne(rp)) return true; } return false; @@ -168,6 +163,7 @@ public class ContextMatcher implements ClassMatcher { prologue(); } + @Override public void prologue() throws IOException { w = new PrintWriter(new DevNullWriter()); } @@ -180,14 +176,17 @@ public class ContextMatcher implements ClassMatcher { */ private static class DevNullWriter extends Writer { + @Override public void write(char[] cbuf, int off, int len) throws IOException { // nothing to do } + @Override public void flush() throws IOException { // nothing to do } + @Override public void close() throws IOException { // nothing to do } diff --git a/src/main/java/org/umlgraph/doclet/ContextView.java b/src/main/java/org/umlgraph/doclet/ContextView.java index 7d8d9cd..040725e 100755 --- a/src/main/java/org/umlgraph/doclet/ContextView.java +++ b/src/main/java/org/umlgraph/doclet/ContextView.java @@ -26,7 +26,7 @@ public class ContextView implements OptionProvider { private Options hideOptions; private Options centerOptions; private Options packageOptions; - private static final String[] HIDE_OPTIONS = new String[] { "-hide" }; + private static final String[] HIDE_OPTIONS = new String[] { "hide" }; public ContextView(String outputFolder, ClassDoc cd, RootDoc root, Options parent) throws IOException { @@ -42,7 +42,7 @@ public class ContextView implements OptionProvider { this.packageOptions.showQualified = false; this.myGlobalOptions = parent.getGlobalOptions(); - this.myGlobalOptions.setOption(new String[] { "-output", outputPath }); + this.myGlobalOptions.setOption(new String[] { "output", outputPath }); this.myGlobalOptions.setOption(HIDE_OPTIONS); this.hideOptions = parent.getGlobalOptions(); @@ -52,7 +52,7 @@ public class ContextView implements OptionProvider { this.centerOptions.nodeFillColor = "lemonChiffon"; this.centerOptions.showQualified = false; - this.matcher = new ContextMatcher(root, Pattern.compile(cd.qualifiedName()), + this.matcher = new ContextMatcher(root, Pattern.compile(Pattern.quote(cd.toString())), myGlobalOptions, true); } @@ -61,8 +61,8 @@ public class ContextView implements OptionProvider { 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())); + this.myGlobalOptions.setOption(new String[] { "output", outputPath }); + matcher.setContextCenter(Pattern.compile(Pattern.quote(cd.toString()))); } public String getDisplayName() { @@ -74,8 +74,9 @@ public class ContextView implements OptionProvider { } public Options getOptionsFor(ClassDoc cd) { - Options opt; - if (globalOptions.matchesHideExpression(cd.toString()) || !matcher.matches(cd)) { + Options opt; + if (globalOptions.matchesHideExpression(cd.qualifiedName()) + || !(matcher.matches(cd) || globalOptions.matchesIncludeExpression(cd.qualifiedName()))) { opt = hideOptions; } else if (cd.equals(this.cd)) { opt = centerOptions; @@ -90,7 +91,7 @@ public class ContextView implements OptionProvider { } public Options getOptionsFor(String name) { - Options opt; + Options opt; if (!matcher.matches(name)) opt = hideOptions; else if (name.equals(cd.name())) @@ -103,15 +104,16 @@ public class ContextView implements OptionProvider { } public void overrideForClass(Options opt, ClassDoc cd) { - opt.setOptions(cd); - if (opt.matchesHideExpression(cd.toString()) || !matcher.matches(cd)) + opt.setOptions(cd); + if (opt.matchesHideExpression(cd.qualifiedName()) + || !(matcher.matches(cd) || opt.matchesIncludeExpression(cd.qualifiedName()))) opt.setOption(HIDE_OPTIONS); if (cd.equals(this.cd)) opt.nodeFillColor = "lemonChiffon"; } public void overrideForClass(Options opt, String className) { - if (!matcher.matches(className)) + if (!(matcher.matches(className) || opt.matchesIncludeExpression(className))) opt.setOption(HIDE_OPTIONS); } diff --git a/src/main/java/org/umlgraph/doclet/Font.java b/src/main/java/org/umlgraph/doclet/Font.java new file mode 100644 index 0000000..09355ea --- /dev/null +++ b/src/main/java/org/umlgraph/doclet/Font.java @@ -0,0 +1,101 @@ +package org.umlgraph.doclet; + +/** + * Class to represent a font for graphviz. + *

    + * This is a fairly complicated model, because it is rather an API into graphviz + * formatting strings rather than a standalone thing.

    } tags, and these can be omitted if not + * set. Inheritance of properties then happens in graphviz. + * + * @author Erich Schubert + */ +public enum Font { + /** Edge label font */ + EDGE, // + /** Node basic */ + NODE, // + /** Normal operation font */ + NORMAL, // + /** Abstract operation font */ + ABSTRACT, // + /** Class name. Inherits from null. */ + CLASS, // + /** Class name of abstract classes (usually italic) */ + CLASS_ABSTRACT, // + /** Package names Inherits from null. */ + PACKAGE, // + /** Tags Inherits from null. */ + TAG; + + public static final String DEFAULT_FONT; + + // Static initialization of further values. + static { + // use an appropriate font depending on the current operating system + if (System.getProperty("os.name").toLowerCase().contains("windows")) { + DEFAULT_FONT = "Arial"; + } else { + DEFAULT_FONT = "Helvetica"; // TODO: can we use just "sans"? + } + } + + /** + * Wraps the text with the appropriate font according to the specified font type + * + * @param opt Options + * @param text Text to wrap + * @return Wrapped text + */ + public String wrap(Options opt, String text) { + if (text.isEmpty() || this == NORMAL) + return text; + String face = null; + double size = -1; + boolean italic = false; + switch (this) { + case EDGE: + case NODE: + // Not used with the wrap function. + throw new UnsupportedOperationException(); + case ABSTRACT: + italic = opt.nodeFontAbstractItalic; + case NORMAL: + break; + case CLASS_ABSTRACT: + italic = opt.nodeFontAbstractItalic; + case CLASS: + face = opt.nodeFontClassName; + size = opt.nodeFontClassSize; + break; + case PACKAGE: + face = opt.nodeFontPackageName; + size = opt.nodeFontPackageSize; + break; + case TAG: + face = opt.nodeFontTagName; + size = opt.nodeFontTagSize; + break; + } + if (face == null && size < 0 && !italic) + return text; + StringBuilder buf = new StringBuilder(text.length() + 100); + if (face != null || size > 0) { + buf.append(" 0) + buf.append(" point-size=\"").append(size).append('"'); + buf.append('>'); + } + if (italic) + buf.append(""); + buf.append(text); + if (italic) + buf.append(""); + if (face != null || size > 0) + buf.append(""); + return buf.toString(); + } +} diff --git a/src/main/java/org/umlgraph/doclet/InterfaceMatcher.java b/src/main/java/org/umlgraph/doclet/InterfaceMatcher.java index 6841cc0..6c63b98 100644 --- a/src/main/java/org/umlgraph/doclet/InterfaceMatcher.java +++ b/src/main/java/org/umlgraph/doclet/InterfaceMatcher.java @@ -26,23 +26,17 @@ public class InterfaceMatcher implements ClassMatcher { // for each interface, recurse, since classes and interfaces // are treated the same in the doclet API - for (ClassDoc iface : cd.interfaces()) { + 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; + return cd.superclass() == null ? false : matches(cd.superclass()); } public boolean matches(String name) { ClassDoc cd = root.classNamed(name); - if(cd == null) - return false; - return matches(cd); + return cd == null ? false : matches(cd); } } diff --git a/src/main/java/org/umlgraph/doclet/Options.java b/src/main/java/org/umlgraph/doclet/Options.java index b33a329..90b7542 100644 --- a/src/main/java/org/umlgraph/doclet/Options.java +++ b/src/main/java/org/umlgraph/doclet/Options.java @@ -29,15 +29,17 @@ import java.io.InputStreamReader; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.net.URL; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; 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.Doc; import com.sun.javadoc.Tag; /** @@ -46,66 +48,54 @@ import com.sun.javadoc.Tag; * @author Diomidis Spinellis */ 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://docs.oracle.com/javase/7/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 = "arial italic"; - } else { - defaultFont = "Helvetica"; - defaultItalicFont = "Helvetica-Oblique"; - } - } - // instance fields - Vector hidePatterns; - boolean showQualified; - boolean showAttributes; - boolean showEnumerations; - boolean showEnumConstants; - boolean showOperations; - boolean showConstructors; - boolean showVisibility; + List hidePatterns = new ArrayList(); + List includePatterns = new ArrayList(); + boolean showQualified = false; + boolean showQualifiedGenerics = false; + boolean hideGenerics = false; + boolean showAttributes = false; + boolean showEnumerations = false; + boolean showEnumConstants = false; + boolean showOperations = false; + boolean showConstructors = false; + boolean showVisibility = false; boolean horizontal; - boolean showType; - boolean showComment; - 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; - Shape shape; - String bgColor; - public String outputFileName; - String outputEncoding; - Map apiDocMap; - String apiDocRoot; - boolean postfixPackage; - boolean useGuillemot; - boolean findViews; - String viewName; - double nodeSep; - double rankSep; - public String outputDirectory; + boolean showType = false; + boolean showComment = false; + boolean autoSize = true; + String edgeFontName = Font.DEFAULT_FONT; + String edgeFontColor = "black"; + String edgeColor = "black"; + double edgeFontSize = 10; + String nodeFontName = Font.DEFAULT_FONT; + boolean nodeFontAbstractItalic = true; + String nodeFontColor = "black"; + double nodeFontSize = 10; + String nodeFillColor = null; + double nodeFontClassSize = -1; + String nodeFontClassName = null; + double nodeFontTagSize = -1; + String nodeFontTagName = null; + double nodeFontPackageSize = -1; + String nodeFontPackageName = null; + Shape shape = Shape.CLASS; + String bgColor = null; + public String outputFileName = "graph.dot"; + String outputEncoding = "ISO-8859-1"; // TODO: default to UTF-8 now? + Map apiDocMap = new HashMap(); + String apiDocRoot = null; + boolean postfixPackage = false; + boolean useGuillemot = true; + boolean findViews = false; + String viewName = null; + double nodeSep = 0.25; + double rankSep = 0.5; + public String outputDirectory = null; /* * Numeric values are preferable to symbolic here. * Symbolic reportedly fail on MacOSX, and also are @@ -115,90 +105,42 @@ public class Options implements Cloneable, OptionProvider { String guilOpen = "«"; // « \u00ab /** Guillemot right (close) */ String guilClose = "»"; // » \u00bb - boolean inferRelationships; - boolean inferDependencies; - boolean collapsibleDiagrams; - RelationPattern contextRelationPattern; - boolean useImports; - Visibility inferDependencyVisibility; - boolean inferDepInPackage; - RelationType inferRelationshipType; - private Vector collPackages; - boolean compact; + boolean inferRelationships = false; + boolean inferDependencies = false; + boolean collapsibleDiagrams = false; + RelationPattern contextRelationPattern = new RelationPattern(RelationDirection.BOTH); + boolean useImports = false; + Visibility inferDependencyVisibility = Visibility.PRIVATE; + boolean inferDepInPackage = false; + RelationType inferRelationshipType = RelationType.NAVASSOC; + private List collPackages = new ArrayList(); + boolean compact = false; + boolean hidePrivateInner = false; // internal option, used by UMLDoc to generate relative links between classes - boolean relativeLinksForSourcePackages; + boolean relativeLinksForSourcePackages = false; // 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 // would have been hidden by the hide pattern "java.*" // TODO: consider making this standard behaviour - boolean strictMatching; - String dotExecutable; + boolean strictMatching = false; + String dotExecutable = "dot"; Options() { - showQualified = false; - showAttributes = false; - showEnumConstants = false; - showOperations = false; - showVisibility = false; - showEnumerations = false; - showConstructors = false; - showType = false; - showComment = 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; - shape = new Shape(); - outputFileName = "graph.dot"; - outputDirectory= null; - outputEncoding = "ISO-8859-1"; - hidePatterns = new Vector(); - apiDocMap = new HashMap(); - apiDocRoot = null; - postfixPackage = false; - useGuillemot = true; - findViews = false; - viewName = null; - contextRelationPattern = new RelationPattern(RelationDirection.BOTH); - inferRelationships = false; - inferDependencies = false; - collapsibleDiagrams = false; - inferDependencyVisibility = Visibility.PRIVATE; - inferDepInPackage = false; - useImports = false; - inferRelationshipType = RelationType.NAVASSOC; - collPackages = new Vector(); - compact = false; - relativeLinksForSourcePackages = false; - nodeSep = 0.25; - rankSep = 0.5; - dotExecutable = "dot"; } - public Object clone() { + @Override + public Object clone() { Options clone = null; try { clone = (Options) super.clone(); } catch (CloneNotSupportedException e) { - // Should not happen + throw new RuntimeException("Cannot clone?!?", e); // Should not happen } // deep clone the hide and collection patterns - clone.hidePatterns = new Vector(hidePatterns); - clone.collPackages= new Vector(collPackages); + clone.hidePatterns = new ArrayList(hidePatterns); + clone.includePatterns = new ArrayList(includePatterns); + clone.collPackages= new ArrayList(collPackages); clone.apiDocMap = new HashMap(apiDocMap); return clone; } @@ -213,6 +155,34 @@ public class Options implements Cloneable, OptionProvider { showVisibility = true; showType = true; } + + /** + * Match strings, ignoring leading -, -!, and !. + * + * @param given Given string + * @param expect Expected string + * @return {@code true} on success + */ + protected static boolean matchOption(String given, String expect) { + return matchOption(given, expect, false); + } + + /** + * Match strings, ignoring leading -, -!, and !. + * + * @param given Given string + * @param expect Expected string + * @param negative May be negative + * @return {@code true} on success + */ + protected static boolean matchOption(String given, String expect, boolean negative) { + int begin = 0, end = given.length(); + if (begin < end && given.charAt(begin) == '-') + ++begin; + if (negative && begin < end && given.charAt(begin) == '!') + ++begin; + return expect.length() == end - begin && expect.regionMatches(0, given, begin, end - begin); + } /** * Return the number of arguments associated with the specified option. @@ -220,63 +190,67 @@ public class Options implements Cloneable, OptionProvider { * 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("-commentname") || - 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("-collapsible") || - option.equals("-inferdep") || - option.equals("-inferdepinpackage") || - option.equals("-compact")) + if(matchOption(option, "qualify", true) || + matchOption(option, "qualifyGenerics", true) || + matchOption(option, "hideGenerics", true) || + matchOption(option, "horizontal", true) || + matchOption(option, "all") || + matchOption(option, "attributes", true) || + matchOption(option, "enumconstants", true) || + matchOption(option, "operations", true) || + matchOption(option, "enumerations", true) || + matchOption(option, "constructors", true) || + matchOption(option, "visibility", true) || + matchOption(option, "types", true) || + matchOption(option, "autosize", true) || + matchOption(option, "commentname", true) || + matchOption(option, "nodefontabstractitalic", true) || + matchOption(option, "postfixpackage", true) || + matchOption(option, "noguillemot", true) || + matchOption(option, "views", true) || + matchOption(option, "inferrel", true) || + matchOption(option, "useimports", true) || + matchOption(option, "collapsible", true) || + matchOption(option, "inferdep", true) || + matchOption(option, "inferdepinpackage", true) || + matchOption(option, "hideprivateinner", true) || + matchOption(option, "compact", true)) 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("-shape") || - 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("-nodesep") || - option.equals("-ranksep") || - option.equals("-dotexecutable") || - option.equals("-link")) + else if(matchOption(option, "nodefillcolor") || + matchOption(option, "nodefontcolor") || + matchOption(option, "nodefontsize") || + matchOption(option, "nodefontname") || + matchOption(option, "nodefontclasssize") || + matchOption(option, "nodefontclassname") || + matchOption(option, "nodefonttagsize") || + matchOption(option, "nodefonttagname") || + matchOption(option, "nodefontpackagesize") || + matchOption(option, "nodefontpackagename") || + matchOption(option, "edgefontcolor") || + matchOption(option, "edgecolor") || + matchOption(option, "edgefontsize") || + matchOption(option, "edgefontname") || + matchOption(option, "shape") || + matchOption(option, "output") || + matchOption(option, "outputencoding") || + matchOption(option, "bgcolor") || + matchOption(option, "hide") || + matchOption(option, "include") || + matchOption(option, "apidocroot") || + matchOption(option, "apidocmap") || + matchOption(option, "d") || + matchOption(option, "view") || + matchOption(option, "inferreltype") || + matchOption(option, "inferdepvis") || + matchOption(option, "collpackages") || + matchOption(option, "nodesep") || + matchOption(option, "ranksep") || + matchOption(option, "dotexecutable") || + matchOption(option, "link")) return 2; - else if(option.equals("-contextPattern") || - option.equals("-linkoffline")) + else if(matchOption(option, "contextPattern") || + matchOption(option, "linkoffline")) return 3; else return 0; @@ -284,231 +258,168 @@ public class Options implements Cloneable, OptionProvider { /** 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) { + if(!matchOption(opt[0], "hide") && optionLength(opt[0]) > opt.length) { System.err.println("Skipping option '" + opt[0] + "', missing argument"); return; } + boolean dash = opt[0].length() > 1 && opt[0].charAt(0) == '-'; + boolean positive = !(opt[0].length() > 1 && opt[0].charAt(dash ? 1 : 0) == '!'); - 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("-commentname")) { - showComment = true; - } else if (opt[0].equals("-!commentname")) { - showComment = false; - } else if(opt[0].equals("-all")) { + if(matchOption(opt[0], "qualify", true)) { + showQualified = positive; + } else if(matchOption(opt[0], "qualifyGenerics", true)) { + showQualifiedGenerics = positive; + } else if(matchOption(opt[0], "hideGenerics", true)) { + hideGenerics = positive; + } else if(matchOption(opt[0], "horizontal", true)) { + horizontal = positive; + } else if(matchOption(opt[0], "attributes", true)) { + showAttributes = positive; + } else if(matchOption(opt[0], "enumconstants", true)) { + showEnumConstants = positive; + } else if(matchOption(opt[0], "operations", true)) { + showOperations = positive; + } else if(matchOption(opt[0], "enumerations", true)) { + showEnumerations = positive; + } else if(matchOption(opt[0], "constructors", true)) { + showConstructors = positive; + } else if(matchOption(opt[0], "visibility", true)) { + showVisibility = positive; + } else if(matchOption(opt[0], "types", true)) { + showType = positive; + } else if(matchOption(opt[0], "autoSize", true)) { + autoSize = positive; + } else if(matchOption(opt[0], "commentname", true)) { + showComment = positive; + } else if(matchOption(opt[0], "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("-shape")) { - shape = new Shape(opt[1]); - } else if (opt[0].equals("-!shape")) { - shape = new Shape(); - } 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) { + } else if(matchOption(opt[0], "bgcolor", true)) { + bgColor = positive ? opt[1] : null; + } else if(matchOption(opt[0], "edgecolor", true)) { + edgeColor = positive ? opt[1] : "black"; + } else if(matchOption(opt[0], "edgefontcolor", true)) { + edgeFontColor = positive ? opt[1] : "black"; + } else if(matchOption(opt[0], "edgefontname", true)) { + edgeFontName = positive ? opt[1] : Font.DEFAULT_FONT; + } else if(matchOption(opt[0], "edgefontsize", true)) { + edgeFontSize = positive ? Double.parseDouble(opt[1]) : 10; + } else if(matchOption(opt[0], "nodefontcolor", true)) { + nodeFontColor = positive ? opt[1] : "black"; + } else if(matchOption(opt[0], "nodefontname", true)) { + nodeFontName = positive ? opt[1] : Font.DEFAULT_FONT; + } else if(matchOption(opt[0], "nodefontabstractitalic", true)) { + nodeFontAbstractItalic = positive; + } else if(matchOption(opt[0], "nodefontsize", true)) { + nodeFontSize = positive ? Double.parseDouble(opt[1]) : 10; + } else if(matchOption(opt[0], "nodefontclassname", true)) { + nodeFontClassName = positive ? opt[1] : null; + } else if(matchOption(opt[0], "nodefontclasssize", true)) { + nodeFontClassSize = positive ? Double.parseDouble(opt[1]) : -1; + } else if(matchOption(opt[0], "nodefonttagname", true)) { + nodeFontTagName = positive ? opt[1] : null; + } else if(matchOption(opt[0], "nodefonttagsize", true)) { + nodeFontTagSize = positive ? Double.parseDouble(opt[1]) : -1; + } else if(matchOption(opt[0], "nodefontpackagename", true)) { + nodeFontPackageName = positive ? opt[1] : null; + } else if(matchOption(opt[0], "nodefontpackagesize", true)) { + nodeFontPackageSize = positive ? Double.parseDouble(opt[1]) : -1; + } else if(matchOption(opt[0], "nodefillcolor", true)) { + nodeFillColor = positive ? opt[1] : null; + } else if(matchOption(opt[0], "shape", true)) { + shape = positive ? Shape.of(opt[1]) : Shape.CLASS; + } else if(matchOption(opt[0], "output", true)) { + outputFileName = positive ? opt[1] : "graph.dot"; + } else if(matchOption(opt[0], "outputencoding", true)) { + outputEncoding = positive ? opt[1] : "ISO-8859-1"; + } else if(matchOption(opt[0], "hide", true)) { + if (positive) { + 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 hidePatterns.clear(); - hidePatterns.add(allPattern); - } else { + } else if(matchOption(opt[0], "include", true)) { + if (positive) { try { - hidePatterns.add(Pattern.compile(opt[1])); + includePatterns.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")) { + } else + includePatterns.clear(); + } else if(matchOption(opt[0], "apidocroot", true)) { + apiDocRoot = positive ? fixApiDocRoot(opt[1]) : null; + } else if(matchOption(opt[0], "apidocmap", true)) { + if (positive) + setApiDocMapFile(opt[1]); + else + apiDocMap.clear(); + } else if(matchOption(opt[0], "noguillemot", true)) { + guilOpen = positive ? "<<" : "\u00ab"; + guilClose = positive ? ">>" : "\u00bb"; + } else if (matchOption(opt[0], "view", true)) { + viewName = positive ? opt[1] : null; + } else if (matchOption(opt[0], "views", true)) { + findViews = positive; + } else if (matchOption(opt[0], "d", true)) { + outputDirectory = positive ? opt[1] : null; + } else if(matchOption(opt[0], "inferrel", true)) { + inferRelationships = positive; + } else if(matchOption(opt[0], "inferreltype", true)) { + if (positive) { 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("-collapsible")) { - collapsibleDiagrams = true; - } else if(opt[0].equals("-!collapsible")) { - collapsibleDiagrams = false; - } 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")) { + } else + inferRelationshipType = RelationType.NAVASSOC; + } else if(matchOption(opt[0], "inferdepvis", true)) { + if (positive) { + 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 + inferDependencyVisibility = Visibility.PRIVATE; + } else if(matchOption(opt[0], "collapsible", true)) { + collapsibleDiagrams = positive; + } else if(matchOption(opt[0], "inferdep", true)) { + inferDependencies = positive; + } else if(matchOption(opt[0], "inferdepinpackage", true)) { + inferDepInPackage = positive; + } else if (matchOption(opt[0], "hideprivateinner", true)) { + hidePrivateInner = positive; + } else if(matchOption(opt[0], "useimports", true)) { + useImports = positive; + } else if (matchOption(opt[0], "collpackages", true)) { + if (positive) { + try { + collPackages.add(Pattern.compile(opt[1])); + } catch (PatternSyntaxException e) { + System.err.println("Skipping invalid pattern " + opt[1]); + } + } else + collPackages.clear(); + } else if (matchOption(opt[0], "compact", true)) { + compact = positive; + } else if (matchOption(opt[0], "postfixpackage", true)) { + postfixPackage = positive; + } else if (matchOption(opt[0], "link")) { addApiDocRoots(opt[1]); - } else if (opt[0].equals("-linkoffline")) { + } else if (matchOption(opt[0], "linkoffline")) { addApiDocRootsOffline(opt[1], opt[2]); - } else if(opt[0].equals("-contextPattern")) { + } else if(matchOption(opt[0], "contextPattern")) { RelationDirection d; RelationType rt; try { d = RelationDirection.valueOf(opt[2].toUpperCase()); @@ -522,27 +433,22 @@ public class Options implements Cloneable, OptionProvider { } - } else if (opt[0].equals("-nodesep")) { + } else if (matchOption(opt[0], "nodesep", true)) { try { - nodeSep = Double.parseDouble(opt[1]); + nodeSep = positive ? Double.parseDouble(opt[1]) : 0.25; } catch (NumberFormatException e) { System.err.println("Skipping invalid nodesep " + opt[1]); } - } else if (opt[0].equals("-!nodesep")) { - nodeSep = 0.25; - } else if (opt[0].equals("-ranksep")) { + } else if (matchOption(opt[0], "ranksep", true)) { try { - rankSep = Double.parseDouble(opt[1]); + rankSep = positive ? Double.parseDouble(opt[1]) : 0.5; } catch (NumberFormatException e) { System.err.println("Skipping invalid ranksep " + opt[1]); } - } else if (opt[0].equals("-!ranksep")) { - rankSep = 0.5; - } else if (opt[0].equals("-dotexecutable")) { - dotExecutable = opt[1]; + } else if (matchOption(opt[0], "dotexecutable")) { + dotExecutable = opt[1]; } else - ; // Do nothing, javadoc will handle the option or complain, if - // needed. + ; // Do nothing, javadoc will handle the option or complain, if needed. } /** @@ -556,7 +462,7 @@ public class Options implements Cloneable, OptionProvider { try { URL url = new URL(packageListUrl + "/package-list"); br = new BufferedReader(new InputStreamReader(url.openStream())); - String line = null; + String line; while((line = br.readLine()) != null) { line = line + "."; Pattern pattern = Pattern.compile(line.replace(".", "\\.") + "[^\\.]*"); @@ -586,7 +492,7 @@ public class Options implements Cloneable, OptionProvider { try { URL url = new URL(packageListUrl + "/package-list"); br = new BufferedReader(new InputStreamReader(url.openStream())); - String line = null; + String line; while((line = br.readLine()) != null) { line = line + "."; Pattern pattern = Pattern.compile(line.replace(".", "\\.") + "[^\\.]*"); @@ -614,11 +520,10 @@ public class Options implements Cloneable, OptionProvider { 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); + apiDocMap.put(Pattern.compile((String) mapEntry.getKey()), thisRoot); } else { System.err.println("No URL for pattern " + mapEntry.getKey()); } @@ -639,7 +544,7 @@ public class Options implements Cloneable, OptionProvider { * match the class name against the regular expressions specified in the * apiDocMap; if a match is found, the associated URL * will be returned. - * + *

    * NOTE: 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. @@ -649,9 +554,7 @@ public class Options implements Cloneable, OptionProvider { apiDocMap.put(Pattern.compile(".*"), DEFAULT_EXTERNAL_APIDOC); for (Map.Entry mapEntry : apiDocMap.entrySet()) { - Pattern regex = mapEntry.getKey(); - Matcher matcher = regex.matcher(className); - if (matcher.matches()) + if (mapEntry.getKey().matcher(className).matches()) return mapEntry.getValue(); } return null; @@ -659,16 +562,15 @@ public class Options implements Cloneable, OptionProvider { /** 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 + "/"; - } - } + if (str == null) + return null; + String fixed = str.trim(); + if (fixed.isEmpty()) + return ""; + if (File.separatorChar != '/') + fixed = fixed.replace(File.separatorChar, '/'); + if (!fixed.endsWith("/")) + fixed = fixed + "/"; return fixed; } @@ -680,15 +582,12 @@ public class Options implements Cloneable, OptionProvider { /** Set the options based on the tag elements of the ClassDoc parameter */ - public void setOptions(ClassDoc p) { + public void setOptions(Doc p) { if (p == null) return; - for (Tag tag : p.tags("opt")) { - String[] opt = StringUtil.tokenize(tag.text()); - opt[0] = "-" + opt[0]; - setOption(opt); - } + for (Tag tag : p.tags("opt")) + setOption(StringUtil.tokenize(tag.text())); } /** @@ -703,32 +602,36 @@ public class Options implements Cloneable, OptionProvider { return true; Matcher m = hidePattern.matcher(s); - if (strictMatching) { - if (m.matches()) { - return true; - } - } else if (m.find()) { + if (strictMatching ? m.matches() : m.find()) return true; - } } return false; } /** * Check if the supplied string matches an entity specified - * with the -hide parameter. + * with the -include parameter. + * @return true if the string matches. + */ + public boolean matchesIncludeExpression(String s) { + for (Pattern includePattern : includePatterns) { + Matcher m = includePattern.matcher(s); + if (strictMatching ? m.matches() : m.find()) + return true; + } + return false; + } + + /** + * Check if the supplied string matches an entity specified + * with the -collpackages 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()) { + if (strictMatching ? m.matches() : m.find()) return true; - } } return false; } @@ -764,7 +667,7 @@ public class Options implements Cloneable, OptionProvider { } public String toString() { - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); sb.append("UMLGRAPH OPTIONS\n"); for(Field f : this.getClass().getDeclaredFields()) { if(!Modifier.isStatic(f.getModifiers())) { diff --git a/src/main/java/org/umlgraph/doclet/PackageMatcher.java b/src/main/java/org/umlgraph/doclet/PackageMatcher.java index c44c85e..99bd7ff 100644 --- a/src/main/java/org/umlgraph/doclet/PackageMatcher.java +++ b/src/main/java/org/umlgraph/doclet/PackageMatcher.java @@ -16,10 +16,9 @@ public class PackageMatcher implements ClassMatcher { } public boolean matches(String name) { - for (ClassDoc cd : packageDoc.allClasses()) { + for (ClassDoc cd : packageDoc.allClasses()) if (cd.qualifiedName().equals(name)) return true; - } return false; } diff --git a/src/main/java/org/umlgraph/doclet/PackageView.java b/src/main/java/org/umlgraph/doclet/PackageView.java index 6329fa5..c66bf6d 100755 --- a/src/main/java/org/umlgraph/doclet/PackageView.java +++ b/src/main/java/org/umlgraph/doclet/PackageView.java @@ -17,15 +17,19 @@ import com.sun.javadoc.RootDoc; */ public class PackageView implements OptionProvider { + private static final String[] HIDE = new String[] { "hide" }; private PackageDoc pd; private OptionProvider parent; private ClassMatcher matcher; private String outputPath; + private Options opt; public PackageView(String outputFolder, PackageDoc pd, RootDoc root, OptionProvider parent) { this.parent = parent; this.pd = pd; this.matcher = new PackageMatcher(pd); + this.opt = parent.getGlobalOptions(); + this.opt.setOptions(pd); this.outputPath = pd.name().replace('.', '/') + "/" + pd.name() + ".dot"; } @@ -36,8 +40,8 @@ public class PackageView implements OptionProvider { public Options getGlobalOptions() { Options go = parent.getGlobalOptions(); - go.setOption(new String[] { "-output", outputPath }); - go.setOption(new String[] { "-hide" }); + go.setOption(new String[] { "output", outputPath }); + go.setOption(HIDE); return go; } @@ -56,15 +60,22 @@ public class PackageView implements OptionProvider { public void overrideForClass(Options opt, ClassDoc cd) { opt.setOptions(cd); - opt.showQualified = false; - if (!matcher.matches(cd) || parent.getGlobalOptions().matchesHideExpression(cd.name())) - opt.setOption(new String[] { "-hide" }); + boolean inPackage = matcher.matches(cd); + if (inPackage) + opt.showQualified = false; + boolean included = inPackage || this.opt.matchesIncludeExpression(cd.qualifiedName()); + if (!included || this.opt.matchesHideExpression(cd.qualifiedName())) + opt.setOption(HIDE); } public void overrideForClass(Options opt, String className) { opt.showQualified = false; - if (!matcher.matches(className)) - opt.setOption(new String[] { "-hide" }); + boolean inPackage = matcher.matches(className); + if (inPackage) + opt.showQualified = false; + boolean included = inPackage || this.opt.matchesIncludeExpression(className); + if (!included || this.opt.matchesHideExpression(className)) + opt.setOption(HIDE); } } diff --git a/src/main/java/org/umlgraph/doclet/PatternMatcher.java b/src/main/java/org/umlgraph/doclet/PatternMatcher.java index 84a1fb1..78a9135 100644 --- a/src/main/java/org/umlgraph/doclet/PatternMatcher.java +++ b/src/main/java/org/umlgraph/doclet/PatternMatcher.java @@ -16,7 +16,6 @@ */ package org.umlgraph.doclet; -import java.util.regex.Matcher; import java.util.regex.Pattern; import com.sun.javadoc.ClassDoc; @@ -38,8 +37,7 @@ public class PatternMatcher implements ClassMatcher { } public boolean matches(String name) { - Matcher matcher = pattern.matcher(name); - return matcher.matches(); + return pattern.matcher(name).matches(); } } diff --git a/src/main/java/org/umlgraph/doclet/RelationDirection.java b/src/main/java/org/umlgraph/doclet/RelationDirection.java index 2203f12..4d3595c 100644 --- a/src/main/java/org/umlgraph/doclet/RelationDirection.java +++ b/src/main/java/org/umlgraph/doclet/RelationDirection.java @@ -13,12 +13,9 @@ public enum RelationDirection { * @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; + // Handle same and nones first: + return (this == d || d == NONE) ? this : // + this == NONE ? d : BOTH; // They are different and not none. } /** @@ -28,10 +25,7 @@ public enum RelationDirection { * @return */ public boolean contains(RelationDirection d) { - if (this == BOTH) - return true; - else - return d == this; + return this == BOTH ? true : (d == this); } /** @@ -40,12 +34,7 @@ public enum RelationDirection { * @return */ public RelationDirection inverse() { - if (this == IN) - return OUT; - else if (this == OUT) - return IN; - else - return this; + return this == IN ? OUT : this == OUT ? IN : this; } }; diff --git a/src/main/java/org/umlgraph/doclet/RelationType.java b/src/main/java/org/umlgraph/doclet/RelationType.java index eb6b4cf..09f33a1 100644 --- a/src/main/java/org/umlgraph/doclet/RelationType.java +++ b/src/main/java/org/umlgraph/doclet/RelationType.java @@ -1,10 +1,34 @@ package org.umlgraph.doclet; /** - * The type of relation that links two entities - * @author wolf + * The type of relation that links two entities, and the graphviz format * + * @author Erich Schubert */ public enum RelationType { - ASSOC, NAVASSOC, HAS, NAVHAS, COMPOSED, NAVCOMPOSED, DEPEND, EXTENDS, IMPLEMENTS; + DEPEND("arrowhead=open,style=dashed,weight=0", false), // Weakest + NAVASSOC("arrowhead=open,weight=1", false), // + ASSOC("arrowhead=none,weight=2", false), // + NAVHAS("arrowhead=open,arrowtail=ediamond,dir=both,weight=3", false), // + HAS("arrowhead=none,arrowtail=ediamond,dir=back,weight=4", false), // + NAVCOMPOSED("arrowhead=open,arrowtail=diamond,dir=both,weight=5", false), // + COMPOSED("arrowhead=none,arrowtail=diamond,dir=back,weight=6", false), // + IMPLEMENTS("arrowtail=empty,style=dashed,dir=back,weight=9", true), // + EXTENDS("arrowtail=empty,dir=back,weight=10", true); + + /** Lower case version of the label */ + public final String lower; + + /** Graphviz style */ + public final String style; + + /** Backwards edges with respect to node ranking */ + public final boolean backorder; + + /** Enum constructors must be private */ + private RelationType(String style, boolean backorder) { + this.lower = toString().toLowerCase(); + this.style = style; + this.backorder = backorder; + } } diff --git a/src/main/java/org/umlgraph/doclet/Shape.java b/src/main/java/org/umlgraph/doclet/Shape.java index b1b9870..54a8cdd 100644 --- a/src/main/java/org/umlgraph/doclet/Shape.java +++ b/src/main/java/org/umlgraph/doclet/Shape.java @@ -18,80 +18,66 @@ package org.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; +import java.util.HashMap; +import java.util.Locale; /** * Properties of node shapes * * @version $Revision$ - * @author Diomidis Spinellis + * @author Erich Schubert */ -public class Shape { +public enum Shape { + CLASS(""), // + NOTE(", shape=note"), // + NODE(", shape=box3d"), // + COMPONENT(", shape=component"), // + PACKAGE(", shape=tab"), // + COLLABORATION(", shape=ellipse, style=dashed"), // + USECASE(", shape=ellipse"), // + ACTIVECLASS(""); - /** Shape's UMLGraph name */ - private String name; + /** Graphviz style */ + public final String style; - /** Construct a default (class) Shape */ - public Shape() { - name = "class"; - } + /** Map for valid shape names */ + private static final HashMap index = new HashMap(16); - /** Construct a Shape through the specified UMLGraph name */ - public Shape(String n) { - name = n; - if (graphvizAttribute() == null) { - System.err.println("Ignoring invalid shape " + n); - name = "class"; + /** Initialize the lookup index */ + static { + for (Shape s : Shape.values()) { + index.put(s.name(), s); + index.put(s.name().toLowerCase(Locale.ROOT), s); } } /** - * Return the GraphViz shape name corresponding to the shape + * Get the shape from a string. This allows both the uppercase and the lowercase + * name. Prefer this to {{@link #valueOf(String)} which only accepts uppercase. + * + * @param s String + * @return Shape */ - public String graphvizAttribute() { - if (name.equals("class")) - return ""; // Default; plaintext - else if (name.equals("note")) - return ", shape=note"; - else if (name.equals("node")) - return ", shape=box3d"; - else if (name.equals("component")) - return ", shape=component"; - else if (name.equals("package")) - return ", shape=tab"; - else if (name.equals("collaboration")) - return ", shape=ellipse, style=dashed"; - else if (name.equals("usecase")) - return ", shape=ellipse"; - else if (name.equals("activeclass")) - return ""; // Default; plaintext - else - return null; + public static Shape of(String s) { + Shape shp = index.get(s); + if (shp != null) + return shp; + System.err.println("Ignoring invalid shape: " + s); + return CLASS; } - /** Return the shape's GraphViz landing port */ - String landingPort() { - if (name.equals("class") || name.equals("activeclass")) - return ":p"; - else - return ""; + /** Enum constructor, must be private! */ + private Shape(String style) { + this.style = style; } /** Return the table border required for the shape */ - String extraColumn(int nRows) { - return name.equals("activeclass") ? ("

    AbstractNode
    abstractMethod()
    concreteMethod()
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // test.InnerNode - c2 [label=<
    InnerNode
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // test.Leaf - c3 [label=<
    Leaf
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - //test.InnerNode extends test.AbstractNode - c1:p -> c2:p [dir=back,arrowtail=empty]; - // test.InnerNode COMPOSED test.AbstractNode - c2:p -> c1:p [taillabel="1", label="has", headlabel="*", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none, arrowtail=diamond, dir=both]; - //test.Leaf extends test.AbstractNode - c1:p -> c3:p [dir=back,arrowtail=empty]; +graph [fontnames="svg"] +edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10,color="black"]; +node [fontname="Helvetica",fontcolor="black",fontsize=10,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +// test.AbstractNode +c1 [label=<
    AbstractNode
    abstractMethod()
    concreteMethod()
    >]; +// test.InnerNode +c2 [label=<
    InnerNode
    >]; +// test.Leaf +c3 [label=<
    Leaf
    >]; +// test.InnerNode extends test.AbstractNode +c1 -> c2 [arrowtail=empty,dir=back,weight=10]; +// test.InnerNode composed test.AbstractNode +c2 -> c1 [arrowhead=none,arrowtail=diamond,dir=back,weight=6,taillabel="1", label="has", headlabel="*"]; +// test.Leaf extends test.AbstractNode +c1 -> c3 [arrowtail=empty,dir=back,weight=10]; } diff --git a/testdata/dot-ref/Inference.dot b/testdata/dot-ref/Inference.dot index fd0b978..64737cf 100644 --- a/testdata/dot-ref/Inference.dot +++ b/testdata/dot-ref/Inference.dot @@ -1,49 +1,50 @@ #!/usr/local/bin/dot # # Class diagram -# Generated by UMLGraph version R5_7_0-10-g786d98 (http://www.umlgraph.org/) +# Generated by UMLGraph version R5_7_2-10-g442559 (http://www.umlgraph.org/) # digraph G { - edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; - node [fontname="Helvetica",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - // A - c66 [label=<
    A
    first : B
    second : B
    third : C
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // B - c67 [label=<
    B
    doSomething(b : B, c : C) : A
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // C - c68 [label=<
    C
    collectionOfA : List<A>
    collectionOfB : ArrayList<B>
    mapOfD : Map<String, D>
    childs : C[]
    anOpaqueList : List<>
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // MyFunnyList - c69 [label=<
    MyFunnyList<T, V>
    myField : V
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // MyList - c70 [label=<
    MyList
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // D - c71 [label=<
    D
    anotherListOfA : MyList
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - //MyFunnyList extends java.util.ArrayList - c72:p -> c69:p [dir=back,arrowtail=empty]; - //MyList extends MyFunnyList - c69:p -> c70:p [dir=back,arrowtail=empty]; - // A HAS B - c66:p -> c67:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none, arrowtail=ediamond, dir=both]; - // A HAS C - c66:p -> c68:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none, arrowtail=ediamond, dir=both]; - // C NAVASSOC B - c68:p -> c67:p [taillabel="", label="", headlabel="*", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open]; - // C NAVASSOC D - c68:p -> c71:p [taillabel="", label="", headlabel="*", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open]; - // C NAVASSOC C - c68:p -> c68:p [taillabel="", label="", headlabel="*", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open]; - // C NAVASSOC java.util.List - c68:p -> c73:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open]; - // D NAVASSOC MyList - c71:p -> c70:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open]; - // B DEPEND A - c67:p -> c66:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open, style=dashed]; - // java.util.List - c73 [label=<
    «interface»
    List<E>
    size() : int
    isEmpty() : boolean
    contains(arg0 : Object) : boolean
    iterator() : Iterator<E>
    toArray() : Object[]
    toArray(arg0 : T[]) : T[]
    add(arg0 : E) : boolean
    remove(arg0 : Object) : boolean
    containsAll(arg0 : Collection<?>) : boolean
    addAll(arg0 : Collection<?>) : boolean
    addAll(arg0 : int, arg1 : Collection<?>) : boolean
    removeAll(arg0 : Collection<?>) : boolean
    retainAll(arg0 : Collection<?>) : boolean
    replaceAll(arg0 : UnaryOperator<E>)
    sort(arg0 : Comparator<?>)
    clear()
    equals(arg0 : Object) : boolean
    hashCode() : int
    get(arg0 : int) : E
    set(arg0 : int, arg1 : E) : E
    add(arg0 : int, arg1 : E)
    remove(arg0 : int) : E
    indexOf(arg0 : Object) : int
    lastIndexOf(arg0 : Object) : int
    listIterator() : ListIterator<E>
    listIterator(arg0 : int) : ListIterator<E>
    subList(arg0 : int, arg1 : int) : List<E>
    spliterator() : Spliterator<E>
    >, URL="http://java.sun.com/j2se/1.4.2/docs/api/java/util/List.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // java.util.ArrayList - c72 [label=<
    ArrayList<E>
    serialVersionUID : long
    DEFAULT_CAPACITY : int
    EMPTY_ELEMENTDATA : Object[]
    DEFAULTCAPACITY_EMPTY_ELEMENTDATA : Object[]
    elementData : Object[]
    size : int
    MAX_ARRAY_SIZE : int
    trimToSize()
    ensureCapacity(arg0 : int)
    ensureCapacityInternal(arg0 : int)
    ensureExplicitCapacity(arg0 : int)
    grow(arg0 : int)
    hugeCapacity(arg0 : int) : int
    size() : int
    isEmpty() : boolean
    contains(arg0 : Object) : boolean
    indexOf(arg0 : Object) : int
    lastIndexOf(arg0 : Object) : int
    clone() : Object
    toArray() : Object[]
    toArray(arg0 : T[]) : T[]
    elementData(arg0 : int) : E
    get(arg0 : int) : E
    set(arg0 : int, arg1 : E) : E
    add(arg0 : E) : boolean
    add(arg0 : int, arg1 : E)
    remove(arg0 : int) : E
    remove(arg0 : Object) : boolean
    fastRemove(arg0 : int)
    clear()
    addAll(arg0 : Collection<?>) : boolean
    addAll(arg0 : int, arg1 : Collection<?>) : boolean
    removeRange(arg0 : int, arg1 : int)
    rangeCheck(arg0 : int)
    rangeCheckForAdd(arg0 : int)
    outOfBoundsMsg(arg0 : int) : String
    removeAll(arg0 : Collection<?>) : boolean
    retainAll(arg0 : Collection<?>) : boolean
    batchRemove(arg0 : Collection<?>, arg1 : boolean) : boolean
    writeObject(arg0 : ObjectOutputStream)
    readObject(arg0 : ObjectInputStream)
    listIterator(arg0 : int) : ListIterator<E>
    listIterator() : ListIterator<E>
    iterator() : Iterator<E>
    subList(arg0 : int, arg1 : int) : List<E>
    subListRangeCheck(arg0 : int, arg1 : int, arg2 : int)
    forEach(arg0 : Consumer<?>)
    spliterator() : Spliterator<E>
    removeIf(arg0 : Predicate<?>) : boolean
    replaceAll(arg0 : UnaryOperator<E>)
    sort(arg0 : Comparator<?>)
    >, URL="http://java.sun.com/j2se/1.4.2/docs/api/java/util/ArrayList.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; +graph [fontnames="svg"] +edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10,color="black"]; +node [fontname="Helvetica",fontcolor="black",fontsize=10,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +// A +c66 [label=<
    A
    first : B
    second : B
    third : C
    >]; +// B +c67 [label=<
    B
    doSomething(b : B, c : C) : A
    >]; +// C +c68 [label=<
    C
    collectionOfA : List<A>
    collectionOfB : ArrayList<B>
    mapOfD : Map<String, D>
    childs : C[]
    anOpaqueList : List<>
    >]; +// MyFunnyList +c69 [label=<
    MyFunnyList<T, V>
    myField : V
    >]; +// MyList +c70 [label=<
    MyList
    >]; +// D +c71 [label=<
    D
    anotherListOfA : MyList
    >]; +// MyFunnyList extends java.util.ArrayList +c72 -> c69 [arrowtail=empty,dir=back,weight=10]; +// MyList extends MyFunnyList +c69 -> c70 [arrowtail=empty,dir=back,weight=10]; +// A has B +c66 -> c67 [arrowhead=none,arrowtail=ediamond,dir=back,weight=4]; +// A has C +c66 -> c68 [arrowhead=none,arrowtail=ediamond,dir=back,weight=4]; +// C navassoc B +c68 -> c67 [arrowhead=open,weight=1,headlabel="*"]; +// C navassoc D +c68 -> c71 [arrowhead=open,weight=1,headlabel="*"]; +// C navassoc C +c68 -> c68 [arrowhead=open,weight=1,headlabel="*"]; +// C navassoc java.util.List +c68 -> c73 [arrowhead=open,weight=1]; +// D navassoc MyList +c71 -> c70 [arrowhead=open,weight=1]; +// B depend A +c67 -> c66 [arrowhead=open,style=dashed,weight=0]; +// java.util.List +c73 [label=<
    «interface»
    List<E>
    size() : int
    isEmpty() : boolean
    contains(arg0 : Object) : boolean
    iterator() : Iterator<E>
    toArray() : Object[]
    toArray(arg0 : T[]) : T[]
    add(arg0 : E) : boolean
    remove(arg0 : Object) : boolean
    containsAll(arg0 : Collection<?>) : boolean
    addAll(arg0 : Collection<?>) : boolean
    addAll(arg0 : int, arg1 : Collection<?>) : boolean
    removeAll(arg0 : Collection<?>) : boolean
    retainAll(arg0 : Collection<?>) : boolean
    replaceAll(arg0 : UnaryOperator<E>)
    sort(arg0 : Comparator<?>)
    clear()
    equals(arg0 : Object) : boolean
    hashCode() : int
    get(arg0 : int) : E
    set(arg0 : int, arg1 : E) : E
    add(arg0 : int, arg1 : E)
    remove(arg0 : int) : E
    indexOf(arg0 : Object) : int
    lastIndexOf(arg0 : Object) : int
    listIterator() : ListIterator<E>
    listIterator(arg0 : int) : ListIterator<E>
    subList(arg0 : int, arg1 : int) : List<E>
    spliterator() : Spliterator<E>
    >, URL="http://docs.oracle.com/javase/7/docs/api/java/util/List.html"]; +// java.util.ArrayList +c72 [label=<
    ArrayList<E>
    serialVersionUID : long
    DEFAULT_CAPACITY : int
    EMPTY_ELEMENTDATA : Object[]
    DEFAULTCAPACITY_EMPTY_ELEMENTDATA : Object[]
    elementData : Object[]
    size : int
    MAX_ARRAY_SIZE : int
    trimToSize()
    ensureCapacity(arg0 : int)
    ensureCapacityInternal(arg0 : int)
    ensureExplicitCapacity(arg0 : int)
    grow(arg0 : int)
    hugeCapacity(arg0 : int) : int
    size() : int
    isEmpty() : boolean
    contains(arg0 : Object) : boolean
    indexOf(arg0 : Object) : int
    lastIndexOf(arg0 : Object) : int
    clone() : Object
    toArray() : Object[]
    toArray(arg0 : T[]) : T[]
    elementData(arg0 : int) : E
    get(arg0 : int) : E
    set(arg0 : int, arg1 : E) : E
    add(arg0 : E) : boolean
    add(arg0 : int, arg1 : E)
    remove(arg0 : int) : E
    remove(arg0 : Object) : boolean
    fastRemove(arg0 : int)
    clear()
    addAll(arg0 : Collection<?>) : boolean
    addAll(arg0 : int, arg1 : Collection<?>) : boolean
    removeRange(arg0 : int, arg1 : int)
    rangeCheck(arg0 : int)
    rangeCheckForAdd(arg0 : int)
    outOfBoundsMsg(arg0 : int) : String
    removeAll(arg0 : Collection<?>) : boolean
    retainAll(arg0 : Collection<?>) : boolean
    batchRemove(arg0 : Collection<?>, arg1 : boolean) : boolean
    writeObject(arg0 : ObjectOutputStream)
    readObject(arg0 : ObjectInputStream)
    listIterator(arg0 : int) : ListIterator<E>
    listIterator() : ListIterator<E>
    iterator() : Iterator<E>
    subList(arg0 : int, arg1 : int) : List<E>
    subListRangeCheck(arg0 : int, arg1 : int, arg2 : int)
    forEach(arg0 : Consumer<?>)
    spliterator() : Spliterator<E>
    removeIf(arg0 : Predicate<?>) : boolean
    replaceAll(arg0 : UnaryOperator<E>)
    sort(arg0 : Comparator<?>)
    >, URL="http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html"]; } diff --git a/testdata/dot-ref/Irp.dot b/testdata/dot-ref/Irp.dot index fe3da57..58bd3d1 100644 --- a/testdata/dot-ref/Irp.dot +++ b/testdata/dot-ref/Irp.dot @@ -5,19 +5,20 @@ # digraph G { - edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; - node [fontname="Helvetica",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - // Application - c74 [label=<
    Application
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // IrpApplication - c75 [label=<
    IrpApplication
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // Main - c76 [label=<
    Main
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - //IrpApplication extends Application - c74:p -> c75:p [dir=back,arrowtail=empty]; - // Main DEPEND IrpApplication - c76:p -> c75:p [taillabel="", label="«friend»", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open, style=dashed]; +graph [fontnames="svg"] +edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10,color="black"]; +node [fontname="Helvetica",fontcolor="black",fontsize=10,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +// Application +c74 [label=<
    Application
    >]; +// IrpApplication +c75 [label=<
    IrpApplication
    >]; +// Main +c76 [label=<
    Main
    >]; +// IrpApplication extends Application +c74 -> c75 [arrowtail=empty,dir=back,weight=10]; +// Main depend IrpApplication +c76 -> c75 [arrowhead=open,style=dashed,weight=0,label="«friend»"]; } diff --git a/testdata/dot-ref/MultiAssoc.dot b/testdata/dot-ref/MultiAssoc.dot index 63a42fa..a2841c0 100644 --- a/testdata/dot-ref/MultiAssoc.dot +++ b/testdata/dot-ref/MultiAssoc.dot @@ -5,15 +5,16 @@ # digraph G { - edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; - node [fontname="Helvetica",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - // A - c81 [label=<
    A
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // C - c83 [label=<
    C
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // A DEPEND C - c81:p -> c83:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open, style=dashed]; +graph [fontnames="svg"] +edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10,color="black"]; +node [fontname="Helvetica",fontcolor="black",fontsize=10,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +// A +c81 [label=<
    A
    >]; +// C +c83 [label=<
    C
    >]; +// A depend C +c81 -> c83 [arrowhead=open,style=dashed,weight=0]; } diff --git a/testdata/dot-ref/MyVector.dot b/testdata/dot-ref/MyVector.dot index e3aeb8a..47aaf55 100644 --- a/testdata/dot-ref/MyVector.dot +++ b/testdata/dot-ref/MyVector.dot @@ -1,31 +1,32 @@ #!/usr/local/bin/dot # # Class diagram -# Generated by UMLGraph version R5_7_0-10-g786d98 (http://www.umlgraph.org/) +# Generated by UMLGraph version R5_7_2-10-g442559 (http://www.umlgraph.org/) # digraph G { - edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; - node [fontname="Helvetica",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - // MyVector - c85 [label=<
    MyVector<E, P>
    ~ addAll(index : int, c : Collection<E>) : boolean
    ~ foo(x : MyVector<P, MyVector<E, E>>) : MyVector<E, P>
    ~ removeAll(c : Collection<?>) : boolean
    ~ set(index : int, element : E) : E
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - //MyVector extends java.util.Vector - c86:p -> c85:p [dir=back,arrowtail=empty]; - //MyVector implements java.util.List - c87:p -> c85:p [dir=back,arrowtail=empty,style=dashed]; - //MyVector implements java.util.RandomAccess - c88:p -> c85:p [dir=back,arrowtail=empty,style=dashed]; - //MyVector implements java.lang.Cloneable - c89:p -> c85:p [dir=back,arrowtail=empty,style=dashed]; - // java.util.RandomAccess - c88 [label=<
    «interface»
    RandomAccess
    >, URL="http://java.sun.com/j2se/1.4.2/docs/api/java/util/RandomAccess.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // java.util.List - c87 [label=<
    «interface»
    List<E>
    + size() : int
    + isEmpty() : boolean
    + contains(arg0 : Object) : boolean
    + iterator() : Iterator<E>
    + toArray() : Object[]
    + toArray(arg0 : T[]) : T[]
    + add(arg0 : E) : boolean
    + remove(arg0 : Object) : boolean
    + containsAll(arg0 : Collection<?>) : boolean
    + addAll(arg0 : Collection<?>) : boolean
    + addAll(arg0 : int, arg1 : Collection<?>) : boolean
    + removeAll(arg0 : Collection<?>) : boolean
    + retainAll(arg0 : Collection<?>) : boolean
    + replaceAll(arg0 : UnaryOperator<E>)
    + sort(arg0 : Comparator<?>)
    + clear()
    + equals(arg0 : Object) : boolean
    + hashCode() : int
    + get(arg0 : int) : E
    + set(arg0 : int, arg1 : E) : E
    + add(arg0 : int, arg1 : E)
    + remove(arg0 : int) : E
    + indexOf(arg0 : Object) : int
    + lastIndexOf(arg0 : Object) : int
    + listIterator() : ListIterator<E>
    + listIterator(arg0 : int) : ListIterator<E>
    + subList(arg0 : int, arg1 : int) : List<E>
    + spliterator() : Spliterator<E>
    >, URL="http://java.sun.com/j2se/1.4.2/docs/api/java/util/List.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // java.lang.Cloneable - c89 [label=<
    «interface»
    Cloneable
    >, URL="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Cloneable.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // java.util.Vector - c86 [label=<
    Vector<E>
    # elementData : Object[]
    # elementCount : int
    # capacityIncrement : int
    - serialVersionUID : long
    - MAX_ARRAY_SIZE : int
    + copyInto(arg0 : Object[])
    + trimToSize()
    + ensureCapacity(arg0 : int)
    - ensureCapacityHelper(arg0 : int)
    - grow(arg0 : int)
    - hugeCapacity(arg0 : int) : int
    + setSize(arg0 : int)
    + capacity() : int
    + size() : int
    + isEmpty() : boolean
    + elements() : Enumeration<E>
    + contains(arg0 : Object) : boolean
    + indexOf(arg0 : Object) : int
    + indexOf(arg0 : Object, arg1 : int) : int
    + lastIndexOf(arg0 : Object) : int
    + lastIndexOf(arg0 : Object, arg1 : int) : int
    + elementAt(arg0 : int) : E
    + firstElement() : E
    + lastElement() : E
    + setElementAt(arg0 : E, arg1 : int)
    + removeElementAt(arg0 : int)
    + insertElementAt(arg0 : E, arg1 : int)
    + addElement(arg0 : E)
    + removeElement(arg0 : Object) : boolean
    + removeAllElements()
    + clone() : Object
    + toArray() : Object[]
    + toArray(arg0 : T[]) : T[]
    ~ elementData(arg0 : int) : E
    + get(arg0 : int) : E
    + set(arg0 : int, arg1 : E) : E
    + add(arg0 : E) : boolean
    + remove(arg0 : Object) : boolean
    + add(arg0 : int, arg1 : E)
    + remove(arg0 : int) : E
    + clear()
    + containsAll(arg0 : Collection<?>) : boolean
    + addAll(arg0 : Collection<?>) : boolean
    + removeAll(arg0 : Collection<?>) : boolean
    + retainAll(arg0 : Collection<?>) : boolean
    + addAll(arg0 : int, arg1 : Collection<?>) : boolean
    + equals(arg0 : Object) : boolean
    + hashCode() : int
    + toString() : String
    + subList(arg0 : int, arg1 : int) : List<E>
    # removeRange(arg0 : int, arg1 : int)
    - writeObject(arg0 : ObjectOutputStream)
    + listIterator(arg0 : int) : ListIterator<E>
    + listIterator() : ListIterator<E>
    + iterator() : Iterator<E>
    + forEach(arg0 : Consumer<?>)
    + removeIf(arg0 : Predicate<?>) : boolean
    + replaceAll(arg0 : UnaryOperator<E>)
    + sort(arg0 : Comparator<?>)
    + spliterator() : Spliterator<E>
    >, URL="http://java.sun.com/j2se/1.4.2/docs/api/java/util/Vector.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; +graph [fontnames="svg"] +edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10,color="black"]; +node [fontname="Helvetica",fontcolor="black",fontsize=10,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +// MyVector +c85 [label=<
    MyVector<E, P>
    ~ addAll(index : int, c : Collection<E>) : boolean
    ~ foo(x : MyVector<P, MyVector<E, E>>) : MyVector<E, P>
    ~ removeAll(c : Collection<?>) : boolean
    ~ set(index : int, element : E) : E
    >]; +// MyVector extends java.util.Vector +c86 -> c85 [arrowtail=empty,dir=back,weight=10]; +// MyVector implements java.util.List +c87 -> c85 [arrowtail=empty,style=dashed,dir=back,weight=9]; +// MyVector implements java.util.RandomAccess +c88 -> c85 [arrowtail=empty,style=dashed,dir=back,weight=9]; +// MyVector implements java.lang.Cloneable +c89 -> c85 [arrowtail=empty,style=dashed,dir=back,weight=9]; +// java.util.RandomAccess +c88 [label=<
    «interface»
    RandomAccess
    >, URL="http://docs.oracle.com/javase/7/docs/api/java/util/RandomAccess.html"]; +// java.util.List +c87 [label=<
    «interface»
    List<E>
    + size() : int
    + isEmpty() : boolean
    + contains(arg0 : Object) : boolean
    + iterator() : Iterator<E>
    + toArray() : Object[]
    + toArray(arg0 : T[]) : T[]
    + add(arg0 : E) : boolean
    + remove(arg0 : Object) : boolean
    + containsAll(arg0 : Collection<?>) : boolean
    + addAll(arg0 : Collection<?>) : boolean
    + addAll(arg0 : int, arg1 : Collection<?>) : boolean
    + removeAll(arg0 : Collection<?>) : boolean
    + retainAll(arg0 : Collection<?>) : boolean
    + replaceAll(arg0 : UnaryOperator<E>)
    + sort(arg0 : Comparator<?>)
    + clear()
    + equals(arg0 : Object) : boolean
    + hashCode() : int
    + get(arg0 : int) : E
    + set(arg0 : int, arg1 : E) : E
    + add(arg0 : int, arg1 : E)
    + remove(arg0 : int) : E
    + indexOf(arg0 : Object) : int
    + lastIndexOf(arg0 : Object) : int
    + listIterator() : ListIterator<E>
    + listIterator(arg0 : int) : ListIterator<E>
    + subList(arg0 : int, arg1 : int) : List<E>
    + spliterator() : Spliterator<E>
    >, URL="http://docs.oracle.com/javase/7/docs/api/java/util/List.html"]; +// java.lang.Cloneable +c89 [label=<
    «interface»
    Cloneable
    >, URL="http://docs.oracle.com/javase/7/docs/api/java/lang/Cloneable.html"]; +// java.util.Vector +c86 [label=<
    Vector<E>
    # elementData : Object[]
    # elementCount : int
    # capacityIncrement : int
    - serialVersionUID : long
    - MAX_ARRAY_SIZE : int
    + copyInto(arg0 : Object[])
    + trimToSize()
    + ensureCapacity(arg0 : int)
    - ensureCapacityHelper(arg0 : int)
    - grow(arg0 : int)
    - hugeCapacity(arg0 : int) : int
    + setSize(arg0 : int)
    + capacity() : int
    + size() : int
    + isEmpty() : boolean
    + elements() : Enumeration<E>
    + contains(arg0 : Object) : boolean
    + indexOf(arg0 : Object) : int
    + indexOf(arg0 : Object, arg1 : int) : int
    + lastIndexOf(arg0 : Object) : int
    + lastIndexOf(arg0 : Object, arg1 : int) : int
    + elementAt(arg0 : int) : E
    + firstElement() : E
    + lastElement() : E
    + setElementAt(arg0 : E, arg1 : int)
    + removeElementAt(arg0 : int)
    + insertElementAt(arg0 : E, arg1 : int)
    + addElement(arg0 : E)
    + removeElement(arg0 : Object) : boolean
    + removeAllElements()
    + clone() : Object
    + toArray() : Object[]
    + toArray(arg0 : T[]) : T[]
    ~ elementData(arg0 : int) : E
    + get(arg0 : int) : E
    + set(arg0 : int, arg1 : E) : E
    + add(arg0 : E) : boolean
    + remove(arg0 : Object) : boolean
    + add(arg0 : int, arg1 : E)
    + remove(arg0 : int) : E
    + clear()
    + containsAll(arg0 : Collection<?>) : boolean
    + addAll(arg0 : Collection<?>) : boolean
    + removeAll(arg0 : Collection<?>) : boolean
    + retainAll(arg0 : Collection<?>) : boolean
    + addAll(arg0 : int, arg1 : Collection<?>) : boolean
    + equals(arg0 : Object) : boolean
    + hashCode() : int
    + toString() : String
    + subList(arg0 : int, arg1 : int) : List<E>
    # removeRange(arg0 : int, arg1 : int)
    - writeObject(arg0 : ObjectOutputStream)
    + listIterator(arg0 : int) : ListIterator<E>
    + listIterator() : ListIterator<E>
    + iterator() : Iterator<E>
    + forEach(arg0 : Consumer<?>)
    + removeIf(arg0 : Predicate<?>) : boolean
    + replaceAll(arg0 : UnaryOperator<E>)
    + sort(arg0 : Comparator<?>)
    + spliterator() : Spliterator<E>
    >, URL="http://docs.oracle.com/javase/7/docs/api/java/util/Vector.html"]; } diff --git a/testdata/dot-ref/Root.dot b/testdata/dot-ref/Root.dot index 4f92d1c..8379501 100644 --- a/testdata/dot-ref/Root.dot +++ b/testdata/dot-ref/Root.dot @@ -5,43 +5,44 @@ # digraph G { - edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; - node [fontname="Helvetica",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - // Root - c90 [label=<
    Root
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // Adapter - c91 [label=<
    Adapter
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // Element - c92 [label=<
    Element
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // ObjectType - c93 [label=<
    ObjectType
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // ObjectMap - c94 [label=<
    ObjectMap
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // Table - c95 [label=<
    Table
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // DataOperation - c96 [label=<
    DataOperation
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // Root ASSOC Adapter - c90:p -> c91:p [taillabel="1..1", label="", headlabel="0..n", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none]; - // Root ASSOC ObjectType - c90:p -> c93:p [taillabel="", label="", headlabel="0..n", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none]; - // Root ASSOC ObjectMap - c90:p -> c94:p [taillabel="", label="", headlabel="0..n", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none]; - // Root ASSOC Table - c90:p -> c95:p [taillabel="", label="", headlabel="0..n", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none]; - // Root ASSOC DataOperation - c90:p -> c96:p [taillabel="", label="", headlabel="0..n", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none]; - //ObjectType extends Element - c92:p -> c93:p [dir=back,arrowtail=empty]; - //ObjectMap extends Element - c92:p -> c94:p [dir=back,arrowtail=empty]; - // ObjectMap HAS ObjectType - c94:p -> c93:p [taillabel="1..1", label="", headlabel="1..1", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none, arrowtail=ediamond, dir=both]; - //Table extends Element - c92:p -> c95:p [dir=back,arrowtail=empty]; - //DataOperation extends Element - c92:p -> c96:p [dir=back,arrowtail=empty]; +graph [fontnames="svg"] +edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10,color="black"]; +node [fontname="Helvetica",fontcolor="black",fontsize=10,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +// Root +c90 [label=<
    Root
    >]; +// Adapter +c91 [label=<
    Adapter
    >]; +// Element +c92 [label=<
    Element
    >]; +// ObjectType +c93 [label=<
    ObjectType
    >]; +// ObjectMap +c94 [label=<
    ObjectMap
    >]; +// Table +c95 [label=<
    Table
    >]; +// DataOperation +c96 [label=<
    DataOperation
    >]; +// Root assoc Adapter +c90 -> c91 [arrowhead=none,weight=2,taillabel="1..1", headlabel="0..n"]; +// Root assoc ObjectType +c90 -> c93 [arrowhead=none,weight=2,headlabel="0..n"]; +// Root assoc ObjectMap +c90 -> c94 [arrowhead=none,weight=2,headlabel="0..n"]; +// Root assoc Table +c90 -> c95 [arrowhead=none,weight=2,headlabel="0..n"]; +// Root assoc DataOperation +c90 -> c96 [arrowhead=none,weight=2,headlabel="0..n"]; +// ObjectType extends Element +c92 -> c93 [arrowtail=empty,dir=back,weight=10]; +// ObjectMap extends Element +c92 -> c94 [arrowtail=empty,dir=back,weight=10]; +// ObjectMap has ObjectType +c94 -> c93 [arrowhead=none,arrowtail=ediamond,dir=back,weight=4,taillabel="1..1", headlabel="1..1"]; +// Table extends Element +c92 -> c95 [arrowtail=empty,dir=back,weight=10]; +// DataOperation extends Element +c92 -> c96 [arrowtail=empty,dir=back,weight=10]; } diff --git a/testdata/dot-ref/RunnableRef.dot b/testdata/dot-ref/RunnableRef.dot index d83d2af..f347d8f 100644 --- a/testdata/dot-ref/RunnableRef.dot +++ b/testdata/dot-ref/RunnableRef.dot @@ -1,19 +1,20 @@ #!/usr/local/bin/dot # # Class diagram -# Generated by UMLGraph version R5_6-9-g37cd34 (http://www.umlgraph.org/) +# Generated by UMLGraph version R5_7_2-10-g442559 (http://www.umlgraph.org/) # digraph G { - edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; - node [fontname="Helvetica",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - // test.RunnableRef - c98 [label=<
    RunnableRef
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // test.RunnableRef DEPEND java.lang.Runnable - c98:p -> c99:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open, style=dashed]; - // java.lang.Runnable - c99 [label=<
    «interface»
    Runnable
    >, URL="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Runnable.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; +graph [fontnames="svg"] +edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10,color="black"]; +node [fontname="Helvetica",fontcolor="black",fontsize=10,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +// test.RunnableRef +c98 [label=<
    RunnableRef
    >]; +// test.RunnableRef depend java.lang.Runnable +c98 -> c99 [arrowhead=open,style=dashed,weight=0]; +// java.lang.Runnable +c99 [label=<
    «interface»
    Runnable
    >, URL="http://docs.oracle.com/javase/7/docs/api/java/lang/Runnable.html"]; } diff --git a/testdata/dot-ref/Style.dot b/testdata/dot-ref/Style.dot index 104c5b5..09ab5f4 100644 --- a/testdata/dot-ref/Style.dot +++ b/testdata/dot-ref/Style.dot @@ -1,27 +1,28 @@ #!/usr/local/bin/dot # # Class diagram -# Generated by UMLGraph version R5_6-9-g37cd34 (http://www.umlgraph.org/) +# Generated by UMLGraph version R5_7_2-10-g442559 (http://www.umlgraph.org/) # digraph G { - edge [fontname="arial",fontsize=10,labelfontname="arial",labelfontsize=10]; - node [fontname="arial",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - // net.sf.whatever.test.AbstractBase - c112 [label=<
    «base»
    AbstractBase
    net.sf.whatever.test
    {since = 1.0}
    field : int
    {since = 1.5}
    abstractMethod()
    concreteMethod() : int
    >, URL="null", fontname="arial", fontcolor="black", fontsize=9.0]; - // net.sf.whatever.test.Composite - c113 [label=<
    Composite
    net.sf.whatever.test
    >, URL="null", fontname="arial", fontcolor="black", fontsize=9.0]; - // net.sf.whatever.test.Style - c114 [label=<
    Style
    net.sf.whatever.test
    >, URL="null", fontname="arial", fontcolor="black", fontsize=9.0]; - //net.sf.whatever.test.Composite extends net.sf.whatever.test.AbstractBase - c112:p -> c113:p [dir=back,arrowtail=empty]; - // net.sf.whatever.test.Composite COMPOSED from.Outer.Space.AlienClass - c113:p -> c115:p [taillabel="1", label="has", headlabel="*", fontname="arial", fontcolor="black", fontsize=10.0, color="black", arrowhead=none, arrowtail=diamond, dir=both]; - //net.sf.whatever.test.Style extends net.sf.whatever.test.AbstractBase - c112:p -> c114:p [dir=back,arrowtail=empty]; - // from.Outer.Space.AlienClass - c115[label=<
    AlienClass
    from.Outer.Space
    >, fontname="arial", fontcolor="black", fontsize=9.0]; +graph [fontnames="svg"] +edge [fontname="arial",fontsize=10,labelfontname="arial",labelfontsize=10,color="black"]; +node [fontname="arial",fontcolor="black",fontsize=9,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +// net.sf.whatever.test.AbstractBase +c112 [label=<
    «base»
    AbstractBase
    net.sf.whatever.test
    {since = 1.0}
    field : int
    {since = 1.5}
    abstractMethod()
    concreteMethod() : int
    >]; +// net.sf.whatever.test.Composite +c113 [label=<
    Composite
    net.sf.whatever.test
    >]; +// net.sf.whatever.test.Style +c114 [label=<
    Style
    net.sf.whatever.test
    >]; +// net.sf.whatever.test.Composite extends net.sf.whatever.test.AbstractBase +c112 -> c113 [arrowtail=empty,dir=back,weight=10]; +// net.sf.whatever.test.Composite composed from.Outer.Space.AlienClass +c113 -> c115 [arrowhead=none,arrowtail=diamond,dir=back,weight=6,taillabel="1",label="has",headlabel="*"]; +// net.sf.whatever.test.Style extends net.sf.whatever.test.AbstractBase +c112 -> c114 [arrowtail=empty,dir=back,weight=10]; +// from.Outer.Space.AlienClass +c115[label=<
    AlienClass
    from.Outer.Space
    >]; } - + diff --git a/testdata/dot-ref/TestHideOp.dot b/testdata/dot-ref/TestHideOp.dot index 661db51..793bf78 100644 --- a/testdata/dot-ref/TestHideOp.dot +++ b/testdata/dot-ref/TestHideOp.dot @@ -5,11 +5,12 @@ # digraph G { - edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; - node [fontname="Helvetica",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - // test.TestHideOp - c117 [label=<
    TestHideOp
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; +graph [fontnames="svg"] +edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10,color="black"]; +node [fontname="Helvetica",fontcolor="black",fontsize=10,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +// test.TestHideOp +c117 [label=<
    TestHideOp
    >]; } diff --git a/testdata/dot-ref/ViewAll.dot b/testdata/dot-ref/ViewAll.dot index bb8a66d..84cf660 100644 --- a/testdata/dot-ref/ViewAll.dot +++ b/testdata/dot-ref/ViewAll.dot @@ -5,27 +5,28 @@ # digraph G { - edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; - node [fontname="Helvetica",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - // gr.spinellis.basic.invoice.InvoiceItem - c355 [label=<
    InvoiceItem
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.basic.invoice.Invoice - c356 [label=<
    Invoice
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.basic.invoice.Customer - c357 [label=<
    Customer
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.basic.product.Product - c358 [label=<
    Product
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.basic.product.Category - c359 [label=<
    Category
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.basic.invoice.InvoiceItem ASSOC gr.spinellis.basic.product.Product - c355:p -> c358:p [taillabel="*", label="", headlabel="1", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none]; - // gr.spinellis.basic.invoice.Invoice ASSOC gr.spinellis.basic.invoice.Customer - c356:p -> c357:p [taillabel="*", label="", headlabel="1", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none]; - // gr.spinellis.basic.invoice.Invoice COMPOSED gr.spinellis.basic.invoice.InvoiceItem - c356:p -> c355:p [taillabel="1", label="", headlabel="*", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none, arrowtail=diamond, dir=both]; - // gr.spinellis.basic.product.Product ASSOC gr.spinellis.basic.product.Category - c358:p -> c359:p [taillabel="*", label="", headlabel="1", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none]; +graph [fontnames="svg"] +edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10,color="black"]; +node [fontname="Helvetica",fontcolor="black",fontsize=10,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +// gr.spinellis.basic.invoice.InvoiceItem +c355 [label=<
    InvoiceItem
    >]; +// gr.spinellis.basic.invoice.Invoice +c356 [label=<
    Invoice
    >]; +// gr.spinellis.basic.invoice.Customer +c357 [label=<
    Customer
    >]; +// gr.spinellis.basic.product.Product +c358 [label=<
    Product
    >]; +// gr.spinellis.basic.product.Category +c359 [label=<
    Category
    >]; +// gr.spinellis.basic.invoice.InvoiceItem assoc gr.spinellis.basic.product.Product +c355 -> c358 [arrowhead=none,weight=2,taillabel="*", headlabel="1"]; +// gr.spinellis.basic.invoice.Invoice assoc gr.spinellis.basic.invoice.Customer +c356 -> c357 [arrowhead=none,weight=2,taillabel="*", headlabel="1"]; +// gr.spinellis.basic.invoice.Invoice composed gr.spinellis.basic.invoice.InvoiceItem +c356 -> c355 [arrowhead=none,arrowtail=diamond,dir=back,weight=6,taillabel="1", headlabel="*"]; +// gr.spinellis.basic.product.Product assoc gr.spinellis.basic.product.Category +c358 -> c359 [arrowhead=none,weight=2,taillabel="*", headlabel="1"]; } diff --git a/testdata/dot-ref/ViewAllDetailed.dot b/testdata/dot-ref/ViewAllDetailed.dot index 079b0f7..7833953 100644 --- a/testdata/dot-ref/ViewAllDetailed.dot +++ b/testdata/dot-ref/ViewAllDetailed.dot @@ -5,27 +5,28 @@ # digraph G { - edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; - node [fontname="Helvetica",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - // gr.spinellis.basic.invoice.InvoiceItem - c317 [label=<
    InvoiceItem
    product : Product
    quantity : int
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.basic.invoice.Invoice - c318 [label=<
    Invoice
    total : double
    items : InvoiceItem[]
    customer : Customer
    addItem(p : Product, quantity : int)
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.basic.invoice.Customer - c319 [label=<
    Customer
    name : String
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.basic.product.Product - c320 [label=<
    Product
    name : String
    stock : int
    price : double
    category : Category
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.basic.product.Category - c321 [label=<
    Category
    name : String
    products : List<>
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.basic.invoice.InvoiceItem ASSOC gr.spinellis.basic.product.Product - c317:p -> c320:p [taillabel="*", label="", headlabel="1", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none]; - // gr.spinellis.basic.invoice.Invoice ASSOC gr.spinellis.basic.invoice.Customer - c318:p -> c319:p [taillabel="*", label="", headlabel="1", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none]; - // gr.spinellis.basic.invoice.Invoice COMPOSED gr.spinellis.basic.invoice.InvoiceItem - c318:p -> c317:p [taillabel="1", label="", headlabel="*", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none, arrowtail=diamond, dir=both]; - // gr.spinellis.basic.product.Product ASSOC gr.spinellis.basic.product.Category - c320:p -> c321:p [taillabel="*", label="", headlabel="1", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none]; +graph [fontnames="svg"] +edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10,color="black"]; +node [fontname="Helvetica",fontcolor="black",fontsize=10,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +// gr.spinellis.basic.invoice.InvoiceItem +c317 [label=<
    InvoiceItem
    product : Product
    quantity : int
    >]; +// gr.spinellis.basic.invoice.Invoice +c318 [label=<
    Invoice
    total : double
    items : InvoiceItem[]
    customer : Customer
    addItem(p : Product, quantity : int)
    >]; +// gr.spinellis.basic.invoice.Customer +c319 [label=<
    Customer
    name : String
    >]; +// gr.spinellis.basic.product.Product +c320 [label=<
    Product
    name : String
    stock : int
    price : double
    category : Category
    >]; +// gr.spinellis.basic.product.Category +c321 [label=<
    Category
    name : String
    products : List<>
    >]; +// gr.spinellis.basic.invoice.InvoiceItem assoc gr.spinellis.basic.product.Product +c317 -> c320 [arrowhead=none,weight=2,taillabel="*", headlabel="1"]; +// gr.spinellis.basic.invoice.Invoice assoc gr.spinellis.basic.invoice.Customer +c318 -> c319 [arrowhead=none,weight=2,taillabel="*", headlabel="1"]; +// gr.spinellis.basic.invoice.Invoice composed gr.spinellis.basic.invoice.InvoiceItem +c318 -> c317 [arrowhead=none,arrowtail=diamond,dir=back,weight=6,taillabel="1", headlabel="*"]; +// gr.spinellis.basic.product.Product assoc gr.spinellis.basic.product.Category +c320 -> c321 [arrowhead=none,weight=2,taillabel="*", headlabel="1"]; } diff --git a/testdata/dot-ref/ViewAtt.dot b/testdata/dot-ref/ViewAtt.dot index 07f93ca..f7ea886 100644 --- a/testdata/dot-ref/ViewAtt.dot +++ b/testdata/dot-ref/ViewAtt.dot @@ -5,27 +5,28 @@ # digraph G { - edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; - node [fontname="Helvetica",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - // gr.spinellis.basic.invoice.InvoiceItem - c279 [label=<
    InvoiceItem
    product
    quantity
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=16.0]; - // gr.spinellis.basic.invoice.Invoice - c280 [label=<
    Invoice
    total
    items
    customer
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=16.0]; - // gr.spinellis.basic.invoice.Customer - c281 [label=<
    Customer
    name
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=16.0]; - // gr.spinellis.basic.product.Product - c282 [label=<
    Product
    name
    stock
    price
    category
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=16.0]; - // gr.spinellis.basic.product.Category - c283 [label=<
    Category
    name
    products
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=16.0]; - // gr.spinellis.basic.invoice.InvoiceItem ASSOC gr.spinellis.basic.product.Product - c279:p -> c282:p [taillabel="*", label="", headlabel="1", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none]; - // gr.spinellis.basic.invoice.Invoice ASSOC gr.spinellis.basic.invoice.Customer - c280:p -> c281:p [taillabel="*", label="", headlabel="1", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none]; - // gr.spinellis.basic.invoice.Invoice COMPOSED gr.spinellis.basic.invoice.InvoiceItem - c280:p -> c279:p [taillabel="1", label="", headlabel="*", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none, arrowtail=diamond, dir=both]; - // gr.spinellis.basic.product.Product ASSOC gr.spinellis.basic.product.Category - c282:p -> c283:p [taillabel="*", label="", headlabel="1", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none]; +graph [fontnames="svg"] +edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10,color="black"]; +node [fontname="Helvetica",fontcolor="black",fontsize=10,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +// gr.spinellis.basic.invoice.InvoiceItem +c279 [label=<
    InvoiceItem
    product
    quantity
    >, fontname="Helvetica", fontcolor="black", fontsize=16.0]; +// gr.spinellis.basic.invoice.Invoice +c280 [label=<
    Invoice
    total
    items
    customer
    >, fontname="Helvetica", fontcolor="black", fontsize=16.0]; +// gr.spinellis.basic.invoice.Customer +c281 [label=<
    Customer
    name
    >, fontname="Helvetica", fontcolor="black", fontsize=16.0]; +// gr.spinellis.basic.product.Product +c282 [label=<
    Product
    name
    stock
    price
    category
    >, fontname="Helvetica", fontcolor="black", fontsize=16.0]; +// gr.spinellis.basic.product.Category +c283 [label=<
    Category
    name
    products
    >, fontname="Helvetica", fontcolor="black", fontsize=16.0]; +// gr.spinellis.basic.invoice.InvoiceItem assoc gr.spinellis.basic.product.Product +c279 -> c282 [arrowhead=none,weight=2,taillabel="*", headlabel="1"]; +// gr.spinellis.basic.invoice.Invoice assoc gr.spinellis.basic.invoice.Customer +c280 -> c281 [arrowhead=none,weight=2,taillabel="*", headlabel="1"]; +// gr.spinellis.basic.invoice.Invoice composed gr.spinellis.basic.invoice.InvoiceItem +c280 -> c279 [arrowhead=none,arrowtail=diamond,dir=back,weight=6,taillabel="1", headlabel="*"]; +// gr.spinellis.basic.product.Product assoc gr.spinellis.basic.product.Category +c282 -> c283 [arrowhead=none,weight=2,taillabel="*", headlabel="1"]; } diff --git a/testdata/dot-ref/ViewChildEmpty.dot b/testdata/dot-ref/ViewChildEmpty.dot index d525e6e..ab25f23 100644 --- a/testdata/dot-ref/ViewChildEmpty.dot +++ b/testdata/dot-ref/ViewChildEmpty.dot @@ -5,15 +5,16 @@ # digraph G { - edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; - node [fontname="Helvetica",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - // gr.spinellis.basic.product.Product - c244 [label=<
    Product
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.basic.product.Category - c245 [label=<
    Category
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.basic.product.Product ASSOC gr.spinellis.basic.product.Category - c244:p -> c245:p [taillabel="*", label="", headlabel="1", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none]; +graph [fontnames="svg"] +edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10,color="black"]; +node [fontname="Helvetica",fontcolor="black",fontsize=10,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +// gr.spinellis.basic.product.Product +c244 [label=<
    Product
    >]; +// gr.spinellis.basic.product.Category +c245 [label=<
    Category
    >]; +// gr.spinellis.basic.product.Product assoc gr.spinellis.basic.product.Category +c244 -> c245 [arrowhead=none,weight=2,taillabel="*", headlabel="1"]; } diff --git a/testdata/dot-ref/ViewChildOverride.dot b/testdata/dot-ref/ViewChildOverride.dot index 1ab5aab..4297729 100644 --- a/testdata/dot-ref/ViewChildOverride.dot +++ b/testdata/dot-ref/ViewChildOverride.dot @@ -5,15 +5,16 @@ # digraph G { - edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; - node [fontname="Helvetica",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - // gr.spinellis.basic.product.Product - c206 [label=<
    Product
    name
    stock
    price
    category
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.basic.product.Category - c207 [label=<
    Category
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.basic.product.Product ASSOC gr.spinellis.basic.product.Category - c206:p -> c207:p [taillabel="*", label="", headlabel="1", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none]; +graph [fontnames="svg"] +edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10,color="black"]; +node [fontname="Helvetica",fontcolor="black",fontsize=10,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +// gr.spinellis.basic.product.Product +c206 [label=<
    Product
    name
    stock
    price
    category
    >]; +// gr.spinellis.basic.product.Category +c207 [label=<
    Category
    >]; +// gr.spinellis.basic.product.Product assoc gr.spinellis.basic.product.Category +c206 -> c207 [arrowhead=none,weight=2,taillabel="*", headlabel="1"]; } diff --git a/testdata/dot-ref/ViewColors.dot b/testdata/dot-ref/ViewColors.dot index 8ab5825..59e9cec 100644 --- a/testdata/dot-ref/ViewColors.dot +++ b/testdata/dot-ref/ViewColors.dot @@ -1,35 +1,36 @@ #!/usr/local/bin/dot # # Class diagram -# Generated by UMLGraph version R5_6-9-g37cd34 (http://www.umlgraph.org/) +# Generated by UMLGraph version R5_7_2-10-g442559 (http://www.umlgraph.org/) # digraph G { - edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; - node [fontname="Helvetica",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - // gr.spinellis.basic.invoice.InvoiceItem - c164 [label=<
    InvoiceItem
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.basic.invoice.Invoice - c165 [label=<
    Invoice
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.basic.invoice.Customer - c166 [label=<
    Customer
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.basic.product.Product - c167 [label=<
    Product
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.basic.product.Category - c168 [label=<
    Category
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.basic.invoice.InvoiceItem ASSOC gr.spinellis.basic.product.Product - c164:p -> c167:p [taillabel="*", label="", headlabel="1", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none]; - // gr.spinellis.basic.invoice.Invoice ASSOC gr.spinellis.basic.invoice.Customer - c165:p -> c166:p [taillabel="*", label="", headlabel="1", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none]; - // gr.spinellis.basic.invoice.Invoice COMPOSED gr.spinellis.basic.invoice.InvoiceItem - c165:p -> c164:p [taillabel="1", label="", headlabel="*", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none, arrowtail=diamond, dir=both]; - // gr.spinellis.basic.product.Product ASSOC gr.spinellis.basic.product.Category - c167:p -> c168:p [taillabel="*", label="", headlabel="1", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none]; - // gr.spinellis.basic.product.Category DEPEND java.util.List - c168:p -> c202:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open, style=dashed]; - // java.util.List - c202 [label=<
    «interface»
    List<E>
    >, URL="http://java.sun.com/j2se/1.4.2/docs/api/java/util/List.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; +graph [fontnames="svg"] +edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10,color="black"]; +node [fontname="Helvetica",fontcolor="black",fontsize=10,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +// gr.spinellis.basic.invoice.InvoiceItem +c164 [label=<
    InvoiceItem
    >]; +// gr.spinellis.basic.invoice.Invoice +c165 [label=<
    Invoice
    >]; +// gr.spinellis.basic.invoice.Customer +c166 [label=<
    Customer
    >]; +// gr.spinellis.basic.product.Product +c167 [label=<
    Product
    >]; +// gr.spinellis.basic.product.Category +c168 [label=<
    Category
    >]; +// gr.spinellis.basic.invoice.InvoiceItem assoc gr.spinellis.basic.product.Product +c164 -> c167 [arrowhead=none,weight=2,taillabel="*", headlabel="1"]; +// gr.spinellis.basic.invoice.Invoice assoc gr.spinellis.basic.invoice.Customer +c165 -> c166 [arrowhead=none,weight=2,taillabel="*", headlabel="1"]; +// gr.spinellis.basic.invoice.Invoice composed gr.spinellis.basic.invoice.InvoiceItem +c165 -> c164 [arrowhead=none,arrowtail=diamond,dir=back,weight=6,taillabel="1", headlabel="*"]; +// gr.spinellis.basic.product.Product assoc gr.spinellis.basic.product.Category +c167 -> c168 [arrowhead=none,weight=2,taillabel="*", headlabel="1"]; +// gr.spinellis.basic.product.Category depend java.util.List +c168 -> c202 [arrowhead=open,style=dashed,weight=0]; +// java.util.List +c202 [label=<
    «interface»
    List<E>
    >, URL="http://docs.oracle.com/javase/7/docs/api/java/util/List.html"]; } diff --git a/testdata/dot-ref/ViewContext.dot b/testdata/dot-ref/ViewContext.dot index 30f4127..a20006b 100644 --- a/testdata/dot-ref/ViewContext.dot +++ b/testdata/dot-ref/ViewContext.dot @@ -1,43 +1,44 @@ #!/usr/local/bin/dot # # Class diagram -# Generated by UMLGraph version R5_7_0-10-g786d98 (http://www.umlgraph.org/) +# Generated by UMLGraph version R5_7_2-10-g442559 (http://www.umlgraph.org/) # digraph G { - edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; - node [fontname="Helvetica",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - // gr.spinellis.context.classes.AClient - c424 [label=<
    AClient
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.context.classes.ASubclass - c426 [label=<
    ASubclass
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.context.classes.E - c427 [label=<
    E
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.context.classes.D - c429 [label=<
    D
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.context.classes.B - c432 [label=<
    B
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.context.classes.ABaseClass - c433 [label=<
    ABaseClass
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.context.classes.A - c434 [label=<
    A
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - //gr.spinellis.context.classes.ASubclass extends gr.spinellis.context.classes.A - c434:p -> c426:p [dir=back,arrowtail=empty]; - //gr.spinellis.context.classes.A extends gr.spinellis.context.classes.ABaseClass - c433:p -> c434:p [dir=back,arrowtail=empty]; - // gr.spinellis.context.classes.D NAVASSOC gr.spinellis.context.classes.A - c429:p -> c434:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open]; - // gr.spinellis.context.classes.A NAVASSOC gr.spinellis.context.classes.B - c434:p -> c432:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open]; - // gr.spinellis.context.classes.A NAVASSOC javax.swing.JComponent - c434:p -> c508:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open]; - // gr.spinellis.context.classes.AClient DEPEND gr.spinellis.context.classes.A - c424:p -> c434:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open, style=dashed]; - // gr.spinellis.context.classes.A DEPEND gr.spinellis.context.classes.E - c434:p -> c427:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open, style=dashed]; - // javax.swing.JComponent - c508 [label=<
    JComponent
    >, URL="http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/JComponent.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; +graph [fontnames="svg"] +edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10,color="black"]; +node [fontname="Helvetica",fontcolor="black",fontsize=10,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +// gr.spinellis.context.classes.AClient +c424 [label=<
    AClient
    >]; +// gr.spinellis.context.classes.ASubclass +c426 [label=<
    ASubclass
    >]; +// gr.spinellis.context.classes.E +c427 [label=<
    E
    >]; +// gr.spinellis.context.classes.D +c429 [label=<
    D
    >]; +// gr.spinellis.context.classes.B +c432 [label=<
    B
    >]; +// gr.spinellis.context.classes.ABaseClass +c433 [label=<
    ABaseClass
    >]; +// gr.spinellis.context.classes.A +c434 [label=<
    A
    >]; +// gr.spinellis.context.classes.ASubclass extends gr.spinellis.context.classes.A +c434 -> c426 [arrowtail=empty,dir=back,weight=10]; +// gr.spinellis.context.classes.A extends gr.spinellis.context.classes.ABaseClass +c433 -> c434 [arrowtail=empty,dir=back,weight=10]; +// gr.spinellis.context.classes.D navassoc gr.spinellis.context.classes.A +c429 -> c434 [arrowhead=open,weight=1]; +// gr.spinellis.context.classes.A navassoc gr.spinellis.context.classes.B +c434 -> c432 [arrowhead=open,weight=1]; +// gr.spinellis.context.classes.A navassoc javax.swing.JComponent +c434 -> c509 [arrowhead=open,weight=1]; +// gr.spinellis.context.classes.AClient depend gr.spinellis.context.classes.A +c424 -> c434 [arrowhead=open,style=dashed,weight=0]; +// gr.spinellis.context.classes.A depend gr.spinellis.context.classes.E +c434 -> c427 [arrowhead=open,style=dashed,weight=0]; +// javax.swing.JComponent +c509 [label=<
    JComponent
    >, URL="http://docs.oracle.com/javase/7/docs/api/javax/swing/JComponent.html"]; } - + diff --git a/testdata/dot-ref/ViewInterfaces.dot b/testdata/dot-ref/ViewInterfaces.dot index c6f8f17..7e1938e 100644 --- a/testdata/dot-ref/ViewInterfaces.dot +++ b/testdata/dot-ref/ViewInterfaces.dot @@ -1,31 +1,32 @@ #!/usr/local/bin/dot # # Class diagram -# Generated by UMLGraph version R5_7_0-10-g786d98 (http://www.umlgraph.org/) +# Generated by UMLGraph version R5_7_2-20-g09fab1 (http://www.umlgraph.org/) # digraph G { - edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; - node [fontname="Helvetica",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - // gr.spinellis.iface.classes.FarImplementor - c533 [label=<
    FarImplementor
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.iface.classes.DirectImplementor - c534 [label=<
    DirectImplementor
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.iface.classes.SubSubFace - c536 [label=<
    «interface»
    SubSubFace
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.iface.classes.SubFace - c537 [label=<
    «interface»
    SubFace
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.iface.classes.Face - c538 [label=<
    «interface»
    Face
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - //gr.spinellis.iface.classes.FarImplementor implements gr.spinellis.iface.classes.SubSubFace - c536:p -> c533:p [dir=back,arrowtail=empty,style=dashed]; - //gr.spinellis.iface.classes.DirectImplementor implements gr.spinellis.iface.classes.Face - c538:p -> c534:p [dir=back,arrowtail=empty,style=dashed]; - //gr.spinellis.iface.classes.SubSubFace implements gr.spinellis.iface.classes.SubFace - c537:p -> c536:p [dir=back,arrowtail=empty,style=dashed]; - //gr.spinellis.iface.classes.SubFace implements gr.spinellis.iface.classes.Face - c538:p -> c537:p [dir=back,arrowtail=empty,style=dashed]; +graph [fontnames="svg"] +edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10,color="black"]; +node [fontname="Helvetica",fontcolor="black",fontsize=10,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +// gr.spinellis.iface.classes.FarImplementor +c534 [label=<
    FarImplementor
    >]; +// gr.spinellis.iface.classes.DirectImplementor +c535 [label=<
    DirectImplementor
    >]; +// gr.spinellis.iface.classes.SubSubFace +c537 [label=<
    «interface»
    SubSubFace
    >]; +// gr.spinellis.iface.classes.SubFace +c538 [label=<
    «interface»
    SubFace
    >]; +// gr.spinellis.iface.classes.Face +c539 [label=<
    «interface»
    Face
    >]; +// gr.spinellis.iface.classes.FarImplementor implements gr.spinellis.iface.classes.SubSubFace +c537 -> c534 [arrowtail=empty,style=dashed,dir=back,weight=9]; +// gr.spinellis.iface.classes.DirectImplementor implements gr.spinellis.iface.classes.Face +c539 -> c535 [arrowtail=empty,style=dashed,dir=back,weight=9]; +// gr.spinellis.iface.classes.SubSubFace implements gr.spinellis.iface.classes.SubFace +c538 -> c537 [arrowtail=empty,style=dashed,dir=back,weight=9]; +// gr.spinellis.iface.classes.SubFace implements gr.spinellis.iface.classes.Face +c539 -> c538 [arrowtail=empty,style=dashed,dir=back,weight=9]; } diff --git a/testdata/dot-ref/ViewProduct.dot b/testdata/dot-ref/ViewProduct.dot index 1c3c1ca..8f2192a 100644 --- a/testdata/dot-ref/ViewProduct.dot +++ b/testdata/dot-ref/ViewProduct.dot @@ -5,15 +5,16 @@ # digraph G { - edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; - node [fontname="Helvetica",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - // gr.spinellis.basic.product.Product - c129 [label=<
    Product
    name
    stock
    price
    category
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.basic.product.Category - c130 [label=<
    Category
    name
    products
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.basic.product.Product ASSOC gr.spinellis.basic.product.Category - c129:p -> c130:p [taillabel="*", label="", headlabel="1", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none]; +graph [fontnames="svg"] +edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10,color="black"]; +node [fontname="Helvetica",fontcolor="black",fontsize=10,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +// gr.spinellis.basic.product.Product +c129 [label=<
    Product
    name
    stock
    price
    category
    >]; +// gr.spinellis.basic.product.Category +c130 [label=<
    Category
    name
    products
    >]; +// gr.spinellis.basic.product.Product assoc gr.spinellis.basic.product.Category +c129 -> c130 [arrowhead=none,weight=2,taillabel="*", headlabel="1"]; } diff --git a/testdata/dot-ref/ViewSubclasses.dot b/testdata/dot-ref/ViewSubclasses.dot index 965eaad..0dc6c7f 100644 --- a/testdata/dot-ref/ViewSubclasses.dot +++ b/testdata/dot-ref/ViewSubclasses.dot @@ -1,31 +1,32 @@ #!/usr/local/bin/dot # # Class diagram -# Generated by UMLGraph version R5_7_0-10-g786d98 (http://www.umlgraph.org/) +# Generated by UMLGraph version R5_7_2-20-g09fab1 (http://www.umlgraph.org/) # digraph G { - edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; - node [fontname="Helvetica",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - // gr.spinellis.subclass.classes.SubOneTwo - c579 [label=<
    SubOneTwo
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.subclass.classes.SubOneOne - c580 [label=<
    SubOneOne
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.subclass.classes.SubTwo - c581 [label=<
    SubTwo
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.subclass.classes.SubOne - c582 [label=<
    SubOne
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.subclass.classes.Super - c583 [label=<
    Super
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - //gr.spinellis.subclass.classes.SubOneTwo extends gr.spinellis.subclass.classes.SubOne - c582:p -> c579:p [dir=back,arrowtail=empty]; - //gr.spinellis.subclass.classes.SubOneOne extends gr.spinellis.subclass.classes.SubOne - c582:p -> c580:p [dir=back,arrowtail=empty]; - //gr.spinellis.subclass.classes.SubTwo extends gr.spinellis.subclass.classes.Super - c583:p -> c581:p [dir=back,arrowtail=empty]; - //gr.spinellis.subclass.classes.SubOne extends gr.spinellis.subclass.classes.Super - c583:p -> c582:p [dir=back,arrowtail=empty]; +graph [fontnames="svg"] +edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10,color="black"]; +node [fontname="Helvetica",fontcolor="black",fontsize=10,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +// gr.spinellis.subclass.classes.SubOneTwo +c580 [label=<
    SubOneTwo
    >]; +// gr.spinellis.subclass.classes.SubOneOne +c581 [label=<
    SubOneOne
    >]; +// gr.spinellis.subclass.classes.SubTwo +c582 [label=<
    SubTwo
    >]; +// gr.spinellis.subclass.classes.SubOne +c583 [label=<
    SubOne
    >]; +// gr.spinellis.subclass.classes.Super +c584 [label=<
    Super
    >]; +// gr.spinellis.subclass.classes.SubOneTwo extends gr.spinellis.subclass.classes.SubOne +c583 -> c580 [arrowtail=empty,dir=back,weight=10]; +// gr.spinellis.subclass.classes.SubOneOne extends gr.spinellis.subclass.classes.SubOne +c583 -> c581 [arrowtail=empty,dir=back,weight=10]; +// gr.spinellis.subclass.classes.SubTwo extends gr.spinellis.subclass.classes.Super +c584 -> c582 [arrowtail=empty,dir=back,weight=10]; +// gr.spinellis.subclass.classes.SubOne extends gr.spinellis.subclass.classes.Super +c584 -> c583 [arrowtail=empty,dir=back,weight=10]; } - + diff --git a/testdata/dot-ref/active.dot b/testdata/dot-ref/active.dot new file mode 100644 index 0000000..02c5a4e --- /dev/null +++ b/testdata/dot-ref/active.dot @@ -0,0 +1,16 @@ +#!/usr/local/bin/dot +# +# Class diagram +# Generated by UMLGraph version R5_7_2-54-gbca0ce (http://www.spinellis.gr/umlgraph/) +# + +digraph G { +graph [fontnames="svg"] +edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10,color="black"]; +node [fontname="Helvetica",fontcolor="black",fontsize=10,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +// Active +c32 [label=<
    Active
    run()
    >]; +} + diff --git a/testdata/dot-ref/advrel.dot b/testdata/dot-ref/advrel.dot index 92e9a8e..2b21798 100644 --- a/testdata/dot-ref/advrel.dot +++ b/testdata/dot-ref/advrel.dot @@ -5,31 +5,32 @@ # digraph G { - edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; - node [fontname="Helvetica",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - // Controller - c5 [label=<
    Controller
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // EmbeddedAgent - c6 [label=<
    EmbeddedAgent
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // PowerManager - c7 [label=<
    PowerManager
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // SetTopController - c8 [label=<
    SetTopController
    authorizationLevel
    startUp()
    shutDown()
    connect()
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // ChannelIterator - c9 [label=<
    ChannelIterator
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // URLStreamHandler - c10 [label=<
    «interface»
    URLStreamHandler
    OpenConnection()
    parseURL()
    setURL()
    toExternalForm()
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - //SetTopController extends Controller - c5:p -> c8:p [dir=back,arrowtail=empty]; - //SetTopController extends EmbeddedAgent - c6:p -> c8:p [dir=back,arrowtail=empty]; - //SetTopController implements URLStreamHandler - c10:p -> c8:p [dir=back,arrowtail=empty,style=dashed]; - // SetTopController NAVASSOC PowerManager - c8:p -> c7:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open]; - // ChannelIterator DEPEND SetTopController - c9:p -> c8:p [taillabel="", label="«friend»", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open, style=dashed]; +graph [fontnames="svg"] +edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10,color="black"]; +node [fontname="Helvetica",fontcolor="black",fontsize=10,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +// Controller +c5 [label=<
    Controller
    >]; +// EmbeddedAgent +c6 [label=<
    EmbeddedAgent
    >]; +// PowerManager +c7 [label=<
    PowerManager
    >]; +// SetTopController +c8 [label=<
    SetTopController
    authorizationLevel
    startUp()
    shutDown()
    connect()
    >]; +// ChannelIterator +c9 [label=<
    ChannelIterator
    >]; +// URLStreamHandler +c10 [label=<
    «interface»
    URLStreamHandler
    OpenConnection()
    parseURL()
    setURL()
    toExternalForm()
    >]; +// SetTopController extends Controller +c5 -> c8 [arrowtail=empty,dir=back,weight=10]; +// SetTopController extends EmbeddedAgent +c6 -> c8 [arrowtail=empty,dir=back,weight=10]; +// SetTopController implements URLStreamHandler +c10 -> c8 [arrowtail=empty,style=dashed,dir=back,weight=9]; +// SetTopController navassoc PowerManager +c8 -> c7 [arrowhead=open,weight=1]; +// ChannelIterator depend SetTopController +c9 -> c8 [arrowhead=open,style=dashed,weight=0,label="«friend»"]; } diff --git a/testdata/dot-ref/assoc.dot b/testdata/dot-ref/assoc.dot index df9b3a1..29715e0 100644 --- a/testdata/dot-ref/assoc.dot +++ b/testdata/dot-ref/assoc.dot @@ -5,20 +5,21 @@ # digraph G { - edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; - node [fontname="Helvetica",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - rankdir=LR; - // UserGroup - c12 [label=<
    UserGroup
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // User - c13 [label=<
    User
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // Password - c14 [label=<
    Password
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // UserGroup ASSOC User - c12:p -> c13:p [taillabel="*", label="", headlabel="*\n\n+user ", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none]; - // User NAVASSOC Password - c13:p -> c14:p [taillabel="1\n\n+owner\r", label="", headlabel="*\n\n+key", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open]; +graph [fontnames="svg"] +edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10,color="black"]; +node [fontname="Helvetica",fontcolor="black",fontsize=10,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +rankdir=LR; +// UserGroup +c12 [label=<
    UserGroup
    >]; +// User +c13 [label=<
    User
    >]; +// Password +c14 [label=<
    Password
    >]; +// UserGroup assoc User +c12 -> c13 [arrowhead=none,weight=2,taillabel="*", headlabel="*\n\n+user "]; +// User navassoc Password +c13 -> c14 [arrowhead=open,weight=1,taillabel="1\n\n+owner\r", headlabel="*\n\n+key"]; } diff --git a/testdata/dot-ref/car.dot b/testdata/dot-ref/car.dot index 8429912..1b3b572 100644 --- a/testdata/dot-ref/car.dot +++ b/testdata/dot-ref/car.dot @@ -5,23 +5,24 @@ # digraph G { - edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; - node [fontname="Helvetica",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - // Tyre - c15 [label=<
    Tyre
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // Engine - c16 [label=<
    Engine
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // Body - c17 [label=<
    Body
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // Car - c18 [label=<
    Car
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // Car COMPOSED Tyre - c18:p -> c15:p [taillabel="1", label="", headlabel="4", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none, arrowtail=diamond, dir=both]; - // Car COMPOSED Engine - c18:p -> c16:p [taillabel="1", label="", headlabel="1", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none, arrowtail=diamond, dir=both]; - // Car COMPOSED Body - c18:p -> c17:p [taillabel="1", label="", headlabel="1", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none, arrowtail=diamond, dir=both]; +graph [fontnames="svg"] +edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10,color="black"]; +node [fontname="Helvetica",fontcolor="black",fontsize=10,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +// Tyre +c15 [label=<
    Tyre
    >]; +// Engine +c16 [label=<
    Engine
    >]; +// Body +c17 [label=<
    Body
    >]; +// Car +c18 [label=<
    Car
    >]; +// Car composed Tyre +c18 -> c15 [arrowhead=none,arrowtail=diamond,dir=back,weight=6,taillabel="1", headlabel="4"]; +// Car composed Engine +c18 -> c16 [arrowhead=none,arrowtail=diamond,dir=back,weight=6,taillabel="1", headlabel="1"]; +// Car composed Body +c18 -> c17 [arrowhead=none,arrowtail=diamond,dir=back,weight=6,taillabel="1", headlabel="1"]; } diff --git a/testdata/dot-ref/catalina.dot b/testdata/dot-ref/catalina.dot index 8fea9a5..b0b624a 100644 --- a/testdata/dot-ref/catalina.dot +++ b/testdata/dot-ref/catalina.dot @@ -5,53 +5,54 @@ # digraph G { - edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; - node [fontname="Helvetica",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - // HttpResponseBase - c19 [label=<
    HttpResponseBase
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // HttpResponseWrapper - c20 [label=<
    HttpResponseWrapper
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // HttpResponseFacade - c21 [label=<
    HttpResponseFacade
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // ResponseWrapper - c22 [label=<
    ResponseWrapper
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // HttpResponse - c23 [label=<
    «interface»
    HttpResponse
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // ResponseBase - c24 [label=<
    ResponseBase
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // HttpServletResponse - c25 [label=<
    «interface»
    HttpServletResponse
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // ResponseFacade - c26 [label=<
    ResponseFacade
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // ServletResponse - c27 [label=<
    «interface»
    ServletResponse
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // Response - c28 [label=<
    «interface»
    Response
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - //HttpResponseBase extends ResponseBase - c24:p -> c19:p [dir=back,arrowtail=empty]; - //HttpResponseBase implements HttpResponse - c23:p -> c19:p [dir=back,arrowtail=empty,style=dashed]; - //HttpResponseBase implements HttpServletResponse - c25:p -> c19:p [dir=back,arrowtail=empty,style=dashed]; - //HttpResponseWrapper extends ResponseWrapper - c22:p -> c20:p [dir=back,arrowtail=empty]; - //HttpResponseWrapper implements HttpResponse - c23:p -> c20:p [dir=back,arrowtail=empty,style=dashed]; - //HttpResponseFacade extends ResponseFacade - c26:p -> c21:p [dir=back,arrowtail=empty]; - //HttpResponseFacade implements HttpServletResponse - c25:p -> c21:p [dir=back,arrowtail=empty,style=dashed]; - //ResponseWrapper implements Response - c28:p -> c22:p [dir=back,arrowtail=empty,style=dashed]; - //HttpResponse implements Response - c28:p -> c23:p [dir=back,arrowtail=empty,style=dashed]; - //ResponseBase implements Response - c28:p -> c24:p [dir=back,arrowtail=empty,style=dashed]; - //ResponseBase implements ServletResponse - c27:p -> c24:p [dir=back,arrowtail=empty,style=dashed]; - //ResponseFacade implements ServletResponse - c27:p -> c26:p [dir=back,arrowtail=empty,style=dashed]; +graph [fontnames="svg"] +edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10,color="black"]; +node [fontname="Helvetica",fontcolor="black",fontsize=10,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +// HttpResponseBase +c19 [label=<
    HttpResponseBase
    >]; +// HttpResponseWrapper +c20 [label=<
    HttpResponseWrapper
    >]; +// HttpResponseFacade +c21 [label=<
    HttpResponseFacade
    >]; +// ResponseWrapper +c22 [label=<
    ResponseWrapper
    >]; +// HttpResponse +c23 [label=<
    «interface»
    HttpResponse
    >]; +// ResponseBase +c24 [label=<
    ResponseBase
    >]; +// HttpServletResponse +c25 [label=<
    «interface»
    HttpServletResponse
    >]; +// ResponseFacade +c26 [label=<
    ResponseFacade
    >]; +// ServletResponse +c27 [label=<
    «interface»
    ServletResponse
    >]; +// Response +c28 [label=<
    «interface»
    Response
    >]; +// HttpResponseBase extends ResponseBase +c24 -> c19 [arrowtail=empty,dir=back,weight=10]; +// HttpResponseBase implements HttpResponse +c23 -> c19 [arrowtail=empty,style=dashed,dir=back,weight=9]; +// HttpResponseBase implements HttpServletResponse +c25 -> c19 [arrowtail=empty,style=dashed,dir=back,weight=9]; +// HttpResponseWrapper extends ResponseWrapper +c22 -> c20 [arrowtail=empty,dir=back,weight=10]; +// HttpResponseWrapper implements HttpResponse +c23 -> c20 [arrowtail=empty,style=dashed,dir=back,weight=9]; +// HttpResponseFacade extends ResponseFacade +c26 -> c21 [arrowtail=empty,dir=back,weight=10]; +// HttpResponseFacade implements HttpServletResponse +c25 -> c21 [arrowtail=empty,style=dashed,dir=back,weight=9]; +// ResponseWrapper implements Response +c28 -> c22 [arrowtail=empty,style=dashed,dir=back,weight=9]; +// HttpResponse implements Response +c28 -> c23 [arrowtail=empty,style=dashed,dir=back,weight=9]; +// ResponseBase implements Response +c28 -> c24 [arrowtail=empty,style=dashed,dir=back,weight=9]; +// ResponseBase implements ServletResponse +c27 -> c24 [arrowtail=empty,style=dashed,dir=back,weight=9]; +// ResponseFacade implements ServletResponse +c27 -> c26 [arrowtail=empty,style=dashed,dir=back,weight=9]; } diff --git a/testdata/dot-ref/class-eg.dot b/testdata/dot-ref/class-eg.dot index 28f9188..3ac8d11 100644 --- a/testdata/dot-ref/class-eg.dot +++ b/testdata/dot-ref/class-eg.dot @@ -5,19 +5,20 @@ # digraph G { - edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; - node [fontname="Helvetica",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - // Person - c30 [label=<
    Person
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // Employee - c31 [label=<
    Employee
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // Client - c32 [label=<
    Client
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - //Employee extends Person - c30:p -> c31:p [dir=back,arrowtail=empty]; - //Client extends Person - c30:p -> c32:p [dir=back,arrowtail=empty]; +graph [fontnames="svg"] +edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10,color="black"]; +node [fontname="Helvetica",fontcolor="black",fontsize=10,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +// Person +c30 [label=<
    Person
    >]; +// Employee +c31 [label=<
    Employee
    >]; +// Client +c32 [label=<
    Client
    >]; +// Employee extends Person +c30 -> c31 [arrowtail=empty,dir=back,weight=10]; +// Client extends Person +c30 -> c32 [arrowtail=empty,dir=back,weight=10]; } diff --git a/testdata/dot-ref/classadd.dot b/testdata/dot-ref/classadd.dot index 966a36c..acc4817 100644 --- a/testdata/dot-ref/classadd.dot +++ b/testdata/dot-ref/classadd.dot @@ -5,11 +5,12 @@ # digraph G { - edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; - node [fontname="Helvetica",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - // ActionQueue - c35 [label=<
    «container»
    ActionQueue
    {version = 3.2}
    add(a : Action)
    add(a : Action, n : int)
    {version = 1.0}
    remove(n : int)
    «query»
    length() : int
    «helper functions»
    reorder()
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; +graph [fontnames="svg"] +edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10,color="black"]; +node [fontname="Helvetica",fontcolor="black",fontsize=10,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +// ActionQueue +c35 [label=<
    «container»
    ActionQueue
    {version = 3.2}
    add(a : Action)
    add(a : Action, n : int)
    {version = 1.0}
    remove(n : int)
    «query»
    length() : int
    «helper functions»
    reorder()
    >]; } diff --git a/testdata/dot-ref/color.dot b/testdata/dot-ref/color.dot index 77937b2..32ccad6 100644 --- a/testdata/dot-ref/color.dot +++ b/testdata/dot-ref/color.dot @@ -5,25 +5,26 @@ # digraph G { - edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; - node [fontname="Serif",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - bgcolor=".7 .9 1"; - - // Pixel - c37 [label=<
    Pixel
    - x : int
    - y : int
    >, URL="null", fontname="arial", fontcolor="white", fontsize=14.0]; - // Red - c38 [label=<
    Red
    >, URL="null", fontname="Serif", fontcolor="black", fontsize=14.0]; - // Green - c39 [label=<
    Green
    >, URL="null", fontname="Serif", fontcolor="black", fontsize=14.0]; - // Blue - c40 [label=<
    Blue
    >, URL="null", fontname="Serif", fontcolor="black", fontsize=14.0]; - // Pixel COMPOSED Red - c37:p -> c38:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="yellow", arrowhead=none, arrowtail=diamond, dir=both]; - // Pixel COMPOSED Green - c37:p -> c39:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="yellow", arrowhead=none, arrowtail=diamond, dir=both]; - // Pixel COMPOSED Blue - c37:p -> c40:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="yellow", arrowhead=none, arrowtail=diamond, dir=both]; +graph [fontnames="svg"] +edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10,color="yellow"]; +node [fontname="Serif",fontcolor="black",fontsize=14,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +bgcolor=".7 .9 1"; + +// Pixel +c37 [label=<
    Pixel
    - x : int
    - y : int
    >]; +// Red +c38 [label=<
    Red
    >]; +// Green +c39 [label=<
    Green
    >]; +// Blue +c40 [label=<
    Blue
    >]; +// Pixel composed Red +c37 -> c38 [arrowhead=none,arrowtail=diamond,dir=back,weight=6]; +// Pixel composed Green +c37 -> c39 [arrowhead=none,arrowtail=diamond,dir=back,weight=6]; +// Pixel composed Blue +c37 -> c40 [arrowhead=none,arrowtail=diamond,dir=back,weight=6]; } - + diff --git a/testdata/dot-ref/ctor.dot b/testdata/dot-ref/ctor.dot index 0826c73..b35fe05 100644 --- a/testdata/dot-ref/ctor.dot +++ b/testdata/dot-ref/ctor.dot @@ -5,11 +5,12 @@ # digraph G { - edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; - node [fontname="Helvetica",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - // Junk - c43 [label=<
    Junk
    - value : int
    + Junk(val : int)
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; +graph [fontnames="svg"] +edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10,color="black"]; +node [fontname="Helvetica",fontcolor="black",fontsize=10,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +// Junk +c43 [label=<
    Junk
    - value : int
    + Junk(val : int)
    >]; } diff --git a/testdata/dot-ref/disable.dot b/testdata/dot-ref/disable.dot index 3759817..7388fd1 100644 --- a/testdata/dot-ref/disable.dot +++ b/testdata/dot-ref/disable.dot @@ -5,15 +5,16 @@ # digraph G { - edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; - node [fontname="Helvetica",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - // Person1 - c45 [label=<
    Person1
    ~ address : String
    ~ name : String
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // Person2 - c46 [label=<
    Person2
    ~ displayName() : String
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // Person3 - c47 [label=<
    Person3
    address : Address
    name : String
    displayName() : String
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; +graph [fontnames="svg"] +edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10,color="black"]; +node [fontname="Helvetica",fontcolor="black",fontsize=10,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +// Person1 +c45 [label=<
    Person1
    ~ address : String
    ~ name : String
    >]; +// Person2 +c46 [label=<
    Person2
    ~ displayName() : String
    >]; +// Person3 +c47 [label=<
    Person3
    address : Address
    name : String
    displayName() : String
    >]; } diff --git a/testdata/dot-ref/extends.dot b/testdata/dot-ref/extends.dot index 2829ebb..6328183 100644 --- a/testdata/dot-ref/extends.dot +++ b/testdata/dot-ref/extends.dot @@ -5,13 +5,14 @@ # digraph G { - edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; - node [fontname="Helvetica",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - // Base - c48 [label=<
    Base
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // Test2 - c49 [label=<
    Test2<B extends Base>
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; +graph [fontnames="svg"] +edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10,color="black"]; +node [fontname="Helvetica",fontcolor="black",fontsize=10,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +// Base +c48 [label=<
    Base
    >]; +// Test2 +c49 [label=<
    Test2<B extends Base>
    >]; } diff --git a/testdata/dot-ref/foo.dot b/testdata/dot-ref/foo.dot index 7c4e2a2..21a8513 100644 --- a/testdata/dot-ref/foo.dot +++ b/testdata/dot-ref/foo.dot @@ -5,21 +5,22 @@ # digraph G { - edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; - node [fontname="Helvetica",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - // a.b.c.UMLOptions - c50 [label=<
    UMLOptions
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // a.b.c.UserGroup - c51 [label=<
    UserGroup
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // a.b.c.User - c52 [label=<
    User
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // a.b.c.Password - c53 [label=<
    Password
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // a.b.c.UserGroup ASSOC a.b.c.User - c51:p -> c52:p [taillabel="*", label="", headlabel="*\n\n+user ", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none]; - // a.b.c.User NAVASSOC a.b.c.Password - c52:p -> c53:p [taillabel="1\n\n+owner\r", label="", headlabel="*\n\n+key", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open]; +graph [fontnames="svg"] +edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10,color="black"]; +node [fontname="Helvetica",fontcolor="black",fontsize=10,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +// a.b.c.UMLOptions +c50 [label=<
    UMLOptions
    >]; +// a.b.c.UserGroup +c51 [label=<
    UserGroup
    >]; +// a.b.c.User +c52 [label=<
    User
    >]; +// a.b.c.Password +c53 [label=<
    Password
    >]; +// a.b.c.UserGroup assoc a.b.c.User +c51 -> c52 [arrowhead=none,weight=2,taillabel="*", headlabel="*\n\n+user "]; +// a.b.c.User navassoc a.b.c.Password +c52 -> c53 [arrowhead=open,weight=1,taillabel="1\n\n+owner\r", headlabel="*\n\n+key"]; } diff --git a/testdata/dot-ref/general.dot b/testdata/dot-ref/general.dot index 75cdc3f..85e9787 100644 --- a/testdata/dot-ref/general.dot +++ b/testdata/dot-ref/general.dot @@ -5,49 +5,50 @@ # digraph G { - edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; - node [fontname="Helvetica",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - // Asset - c55 [label=<
    Asset
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // InterestBearingItem - c56 [label=<
    InterestBearingItem
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // InsurableItem - c57 [label=<
    InsurableItem
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // BankAccount - c58 [label=<
    BankAccount
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // RealEstate - c59 [label=<
    RealEstate
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // Security - c60 [label=<
    Security
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // Stock - c61 [label=<
    Stock
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // Bond - c62 [label=<
    Bond
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // CheckingAccount - c63 [label=<
    CheckingAccount
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // SavingsAccount - c64 [label=<
    SavingsAccount
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - //BankAccount extends Asset - c55:p -> c58:p [dir=back,arrowtail=empty]; - //BankAccount extends InsurableItem - c57:p -> c58:p [dir=back,arrowtail=empty]; - //BankAccount extends InterestBearingItem - c56:p -> c58:p [dir=back,arrowtail=empty]; - //RealEstate extends Asset - c55:p -> c59:p [dir=back,arrowtail=empty]; - //RealEstate extends InsurableItem - c57:p -> c59:p [dir=back,arrowtail=empty]; - //Security extends Asset - c55:p -> c60:p [dir=back,arrowtail=empty]; - //Stock extends Security - c60:p -> c61:p [dir=back,arrowtail=empty]; - //Bond extends Security - c60:p -> c62:p [dir=back,arrowtail=empty]; - //CheckingAccount extends BankAccount - c58:p -> c63:p [dir=back,arrowtail=empty]; - //SavingsAccount extends BankAccount - c58:p -> c64:p [dir=back,arrowtail=empty]; +graph [fontnames="svg"] +edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10,color="black"]; +node [fontname="Helvetica",fontcolor="black",fontsize=10,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +// Asset +c55 [label=<
    Asset
    >]; +// InterestBearingItem +c56 [label=<
    InterestBearingItem
    >]; +// InsurableItem +c57 [label=<
    InsurableItem
    >]; +// BankAccount +c58 [label=<
    BankAccount
    >]; +// RealEstate +c59 [label=<
    RealEstate
    >]; +// Security +c60 [label=<
    Security
    >]; +// Stock +c61 [label=<
    Stock
    >]; +// Bond +c62 [label=<
    Bond
    >]; +// CheckingAccount +c63 [label=<
    CheckingAccount
    >]; +// SavingsAccount +c64 [label=<
    SavingsAccount
    >]; +// BankAccount extends Asset +c55 -> c58 [arrowtail=empty,dir=back,weight=10]; +// BankAccount extends InsurableItem +c57 -> c58 [arrowtail=empty,dir=back,weight=10]; +// BankAccount extends InterestBearingItem +c56 -> c58 [arrowtail=empty,dir=back,weight=10]; +// RealEstate extends Asset +c55 -> c59 [arrowtail=empty,dir=back,weight=10]; +// RealEstate extends InsurableItem +c57 -> c59 [arrowtail=empty,dir=back,weight=10]; +// Security extends Asset +c55 -> c60 [arrowtail=empty,dir=back,weight=10]; +// Stock extends Security +c60 -> c61 [arrowtail=empty,dir=back,weight=10]; +// Bond extends Security +c60 -> c62 [arrowtail=empty,dir=back,weight=10]; +// CheckingAccount extends BankAccount +c58 -> c63 [arrowtail=empty,dir=back,weight=10]; +// SavingsAccount extends BankAccount +c58 -> c64 [arrowtail=empty,dir=back,weight=10]; } diff --git a/testdata/dot-ref/java5.dot b/testdata/dot-ref/java5.dot index 3364bc4..18c40e7 100644 --- a/testdata/dot-ref/java5.dot +++ b/testdata/dot-ref/java5.dot @@ -5,13 +5,14 @@ # digraph G { - edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; - node [fontname="Helvetica",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - // Java5 - c78 [label=<
    Java5
    ~ state : Java5.States
    - specifiedPackages : Set<String>
    + printAll(args : String[])
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // Java5.States - c79 [label=<
    «enumeration»
    States
    start
    dash
    colon
    space
    open
    w
    close
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; +graph [fontnames="svg"] +edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10,color="black"]; +node [fontname="Helvetica",fontcolor="black",fontsize=10,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +// Java5 +c78 [label=<
    Java5
    ~ state : Java5.States
    - specifiedPackages : Set<String>
    + printAll(args : String[])
    >]; +// Java5.States +c79 [label=<
    «enumeration»
    States
    start
    dash
    colon
    space
    open
    w
    close
    >]; } diff --git a/testdata/dot-ref/schema.dot b/testdata/dot-ref/schema.dot index a723eab..6d97162 100644 --- a/testdata/dot-ref/schema.dot +++ b/testdata/dot-ref/schema.dot @@ -5,33 +5,34 @@ # digraph G { - edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; - node [fontname="Helvetica",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - // School - c103 [label=<
    School
    name : Name
    address : String
    phone : Number
    addStudent()
    removeStudent()
    getStudent()
    getAllStudents()
    addDepartment()
    removeDepartment()
    getDepartment()
    getAllDepartments()
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // Department - c104 [label=<
    Department
    name : Name
    addInstructor()
    removeInstructor()
    getInstructor()
    getAllInstructors()
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // Student - c105 [label=<
    Student
    name : Name
    studentID : Number
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // Course - c106 [label=<
    Course
    name : Name
    courseID : Number
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // Instructor - c107 [label=<
    Instructor
    name : Name
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // School HAS Student - c103:p -> c105:p [taillabel="1..*", label="Member", headlabel="*", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none, arrowtail=ediamond, dir=both]; - // School COMPOSED Department - c103:p -> c104:p [taillabel="1..*", label="Has", headlabel="1..*", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none, arrowtail=diamond, dir=both]; - // Department ASSOC Course - c104:p -> c106:p [taillabel="1..*", label="", headlabel="1..*", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none]; - // Department ASSOC Instructor - c104:p -> c107:p [taillabel="0..*", label="", headlabel="0..1 chairperson", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none]; - // Department HAS Instructor - c104:p -> c107:p [taillabel="1..*", label="AssignedTo", headlabel="1..*", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none, arrowtail=ediamond, dir=both]; - // Student ASSOC Course - c105:p -> c106:p [taillabel="*", label="Attends", headlabel="*", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none]; - // Instructor ASSOC Course - c107:p -> c106:p [taillabel="1..*", label="Teaches", headlabel="*", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=none]; +graph [fontnames="svg"] +edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10,color="black"]; +node [fontname="Helvetica",fontcolor="black",fontsize=10,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +// School +c103 [label=<
    School
    name : Name
    address : String
    phone : Number
    addStudent()
    removeStudent()
    getStudent()
    getAllStudents()
    addDepartment()
    removeDepartment()
    getDepartment()
    getAllDepartments()
    >]; +// Department +c104 [label=<
    Department
    name : Name
    addInstructor()
    removeInstructor()
    getInstructor()
    getAllInstructors()
    >]; +// Student +c105 [label=<
    Student
    name : Name
    studentID : Number
    >]; +// Course +c106 [label=<
    Course
    name : Name
    courseID : Number
    >]; +// Instructor +c107 [label=<
    Instructor
    name : Name
    >]; +// School has Student +c103 -> c105 [arrowhead=none,arrowtail=ediamond,dir=back,weight=4,taillabel="1..*", label="Member", headlabel="*"]; +// School composed Department +c103 -> c104 [arrowhead=none,arrowtail=diamond,dir=back,weight=6,taillabel="1..*", label="Has", headlabel="1..*"]; +// Department assoc Course +c104 -> c106 [arrowhead=none,weight=2,taillabel="1..*", headlabel="1..*"]; +// Department assoc Instructor +c104 -> c107 [arrowhead=none,weight=2,taillabel="0..*", headlabel="0..1 chairperson"]; +// Department has Instructor +c104 -> c107 [arrowhead=none,arrowtail=ediamond,dir=back,weight=4,taillabel="1..*", label="AssignedTo", headlabel="1..*"]; +// Student assoc Course +c105 -> c106 [arrowhead=none,weight=2,taillabel="*", label="Attends", headlabel="*"]; +// Instructor assoc Course +c107 -> c106 [arrowhead=none,weight=2,taillabel="1..*", label="Teaches", headlabel="*"]; } diff --git a/testdata/dot-ref/strip.dot b/testdata/dot-ref/strip.dot index 6c7ca58..a40df9c 100644 --- a/testdata/dot-ref/strip.dot +++ b/testdata/dot-ref/strip.dot @@ -5,13 +5,14 @@ # digraph G { - edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; - node [fontname="Helvetica",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - // Java5 - c109 [label=<
    Java5
    ~ state : Java5.States
    + specifiedPackages : Set<String>
    + printAll(args : String[])
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // Java5.States - c110 [label=<
    «enumeration»
    States
    start
    dash
    colon
    space
    open
    w
    close
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; +graph [fontnames="svg"] +edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10,color="black"]; +node [fontname="Helvetica",fontcolor="black",fontsize=10,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +// Java5 +c109 [label=<
    Java5
    ~ state : Java5.States
    + specifiedPackages : Set<String>
    + printAll(args : String[])
    >]; +// Java5.States +c110 [label=<
    «enumeration»
    States
    start
    dash
    colon
    space
    open
    w
    close
    >]; } diff --git a/testdata/dot-ref/vis.dot b/testdata/dot-ref/vis.dot index b44fd58..db7ad2b 100644 --- a/testdata/dot-ref/vis.dot +++ b/testdata/dot-ref/vis.dot @@ -5,11 +5,12 @@ # digraph G { - edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; - node [fontname="Helvetica",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - // Toolbar - c120 [label=<
    Toolbar
    # currentSelection : Tool
    # toolCount : Integer
    + pickItem(i : Integer)
    + addTool(t : Tool)
    + removeTool(i : Integer)
    + getTool() : Tool
    # checkOrphans()
    - compact()
    >, URL="null", fontname="Helvetica", fontcolor="black", fontsize=10.0]; +graph [fontnames="svg"] +edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10,color="black"]; +node [fontname="Helvetica",fontcolor="black",fontsize=10,shape=plaintext,margin=0,width=0,height=0]; +nodesep=0.25; +ranksep=0.5; +// Toolbar +c120 [label=<
    Toolbar
    # currentSelection : Tool
    # toolCount : Integer
    + pickItem(i : Integer)
    + addTool(t : Tool)
    + removeTool(i : Integer)
    + getTool() : Tool
    # checkOrphans()
    - compact()
    >]; } diff --git a/testdata/java/active.java b/testdata/java/active.java new file mode 100644 index 0000000..5b63708 --- /dev/null +++ b/testdata/java/active.java @@ -0,0 +1,13 @@ +/** + * Active classes + * + * @opt operations + * @opt shape activeclass + * @hidden + */ +class UMLOptions {} + +class Active { + protected int hidden; + public void run() {}; +} diff --git a/testdata/java/extends.java b/testdata/java/extends.java index 6cd4188..d9bd341 100644 --- a/testdata/java/extends.java +++ b/testdata/java/extends.java @@ -1,3 +1,2 @@ - class Base {} -class Test2 {} +class Test2 {} diff --git a/testdata/umldoc-ref/allclasses-frame.html b/testdata/umldoc-ref/allclasses-frame.html index 9846d5f..c947c3d 100644 --- a/testdata/umldoc-ref/allclasses-frame.html +++ b/testdata/umldoc-ref/allclasses-frame.html @@ -2,9 +2,9 @@ - + All Classes - + diff --git a/testdata/umldoc-ref/allclasses-noframe.html b/testdata/umldoc-ref/allclasses-noframe.html index e0eaff6..4980e93 100644 --- a/testdata/umldoc-ref/allclasses-noframe.html +++ b/testdata/umldoc-ref/allclasses-noframe.html @@ -2,9 +2,9 @@ - + All Classes - + diff --git a/testdata/umldoc-ref/constant-values.html b/testdata/umldoc-ref/constant-values.html index a014f71..2853bc5 100644 --- a/testdata/umldoc-ref/constant-values.html +++ b/testdata/umldoc-ref/constant-values.html @@ -2,9 +2,9 @@ - + Constant Field Values - + diff --git a/testdata/umldoc-ref/deprecated-list.html b/testdata/umldoc-ref/deprecated-list.html index 83cd591..566d2c4 100644 --- a/testdata/umldoc-ref/deprecated-list.html +++ b/testdata/umldoc-ref/deprecated-list.html @@ -2,9 +2,9 @@ - + Deprecated List - + diff --git a/testdata/umldoc-ref/gr/spinellis/invoice/Customer.dot b/testdata/umldoc-ref/gr/spinellis/invoice/Customer.dot index bbe2826..995b9bb 100644 --- a/testdata/umldoc-ref/gr/spinellis/invoice/Customer.dot +++ b/testdata/umldoc-ref/gr/spinellis/invoice/Customer.dot @@ -1,7 +1,7 @@ #!/usr/local/bin/dot # # Class diagram -# Generated by UMLGraph version R5_7_0-10-g786d98 (http://www.umlgraph.org/) +# Generated by UMLGraph version R5_7_2-11-g86574a (http://www.umlgraph.org/) # digraph G { @@ -10,14 +10,14 @@ digraph G { nodesep=0.25; ranksep=0.5; // gr.spinellis.invoice.Invoice - c33 [label=<
    Invoice
    >, URL="./Invoice.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; + c33 [label=<
    Invoice
    >, URL="./Invoice.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; // gr.spinellis.invoice.Customer - c34 [label=<
    Customer
    >, URL="./Customer.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; + c34 [label=<
    Customer
    >, URL="./Customer.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; // gr.spinellis.invoice.Invoice NAVASSOC gr.spinellis.invoice.Customer c33:p -> c34:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open]; // gr.spinellis.invoice.Customer NAVASSOC java.lang.String c34:p -> c44:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open]; // java.lang.String - c44 [label=<
    String
    java.lang
    >, URL="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/String.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; + c44 [label=<
    String
    java.lang
    >, URL="http://docs.oracle.com/javase/7/docs/api/java/lang/String.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; } diff --git a/testdata/umldoc-ref/gr/spinellis/invoice/Customer.html b/testdata/umldoc-ref/gr/spinellis/invoice/Customer.html index d866a92..959bfeb 100644 --- a/testdata/umldoc-ref/gr/spinellis/invoice/Customer.html +++ b/testdata/umldoc-ref/gr/spinellis/invoice/Customer.html @@ -2,9 +2,9 @@ - + Customer - + @@ -87,16 +87,8 @@

    gr.spinellis.invoice

    Class Customer

    - - - - - - - - - -
    Package class diagram package Customer
    + +
      diff --git a/testdata/umldoc-ref/gr/spinellis/invoice/Invoice.dot b/testdata/umldoc-ref/gr/spinellis/invoice/Invoice.dot index 0139895..19d299b 100644 --- a/testdata/umldoc-ref/gr/spinellis/invoice/Invoice.dot +++ b/testdata/umldoc-ref/gr/spinellis/invoice/Invoice.dot @@ -1,7 +1,7 @@ #!/usr/local/bin/dot # # Class diagram -# Generated by UMLGraph version R5_7_0-10-g786d98 (http://www.umlgraph.org/) +# Generated by UMLGraph version R5_7_2-11-g86574a (http://www.umlgraph.org/) # digraph G { @@ -10,13 +10,13 @@ digraph G { nodesep=0.25; ranksep=0.5; // gr.spinellis.invoice.InvoiceItem - c45 [label=<
      InvoiceItem
      >, URL="./InvoiceItem.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; + c45 [label=<
      InvoiceItem
      >, URL="./InvoiceItem.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; // gr.spinellis.invoice.Invoice - c46 [label=<
      Invoice
      >, URL="./Invoice.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; + c46 [label=<
      Invoice
      >, URL="./Invoice.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; // gr.spinellis.invoice.Customer - c47 [label=<
      Customer
      >, URL="./Customer.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; + c47 [label=<
      Customer
      >, URL="./Customer.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; // gr.spinellis.product.Product - c48 [label=<
      Product
      gr.spinellis.product
      >, URL="../product/Product.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; + c48 [label=<
      Product
      gr.spinellis.product
      >, URL="../product/Product.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; // gr.spinellis.invoice.InvoiceItem NAVASSOC gr.spinellis.product.Product c45:p -> c48:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open]; // gr.spinellis.invoice.Invoice NAVASSOC gr.spinellis.invoice.InvoiceItem @@ -28,6 +28,6 @@ digraph G { // gr.spinellis.invoice.Invoice DEPEND gr.spinellis.product.Product c46:p -> c48:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open, style=dashed]; // java.util.Date - c50 [label=<
      Date
      java.util
      >, URL="http://java.sun.com/j2se/1.4.2/docs/api/java/util/Date.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; + c50 [label=<
      Date
      java.util
      >, URL="http://docs.oracle.com/javase/7/docs/api/java/util/Date.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; } diff --git a/testdata/umldoc-ref/gr/spinellis/invoice/Invoice.html b/testdata/umldoc-ref/gr/spinellis/invoice/Invoice.html index 2ceec08..1d6e890 100644 --- a/testdata/umldoc-ref/gr/spinellis/invoice/Invoice.html +++ b/testdata/umldoc-ref/gr/spinellis/invoice/Invoice.html @@ -2,9 +2,9 @@ - + Invoice - + @@ -93,20 +93,8 @@ var activeTableTab = "activeTableTab";
      gr.spinellis.invoice

      Class Invoice

      - - - - - - - - - - - - - -
      Package class diagram package Invoice
      + +
        diff --git a/testdata/umldoc-ref/gr/spinellis/invoice/InvoiceItem.dot b/testdata/umldoc-ref/gr/spinellis/invoice/InvoiceItem.dot index 7bb3910..e55613f 100644 --- a/testdata/umldoc-ref/gr/spinellis/invoice/InvoiceItem.dot +++ b/testdata/umldoc-ref/gr/spinellis/invoice/InvoiceItem.dot @@ -1,7 +1,7 @@ #!/usr/local/bin/dot # # Class diagram -# Generated by UMLGraph version R5_7_0-10-g786d98 (http://www.umlgraph.org/) +# Generated by UMLGraph version R5_7_2-11-g86574a (http://www.umlgraph.org/) # digraph G { @@ -10,11 +10,11 @@ digraph G { nodesep=0.25; ranksep=0.5; // gr.spinellis.invoice.InvoiceItem - c51 [label=<
        InvoiceItem
        >, URL="./InvoiceItem.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; + c51 [label=<
        InvoiceItem
        >, URL="./InvoiceItem.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; // gr.spinellis.invoice.Invoice - c52 [label=<
        Invoice
        >, URL="./Invoice.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; + c52 [label=<
        Invoice
        >, URL="./Invoice.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; // gr.spinellis.product.Product - c54 [label=<
        Product
        gr.spinellis.product
        >, URL="../product/Product.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; + c54 [label=<
        Product
        gr.spinellis.product
        >, URL="../product/Product.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; // gr.spinellis.invoice.InvoiceItem NAVASSOC gr.spinellis.product.Product c51:p -> c54:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open]; // gr.spinellis.invoice.Invoice NAVASSOC gr.spinellis.invoice.InvoiceItem diff --git a/testdata/umldoc-ref/gr/spinellis/invoice/InvoiceItem.html b/testdata/umldoc-ref/gr/spinellis/invoice/InvoiceItem.html index e4bc5c7..fe26859 100644 --- a/testdata/umldoc-ref/gr/spinellis/invoice/InvoiceItem.html +++ b/testdata/umldoc-ref/gr/spinellis/invoice/InvoiceItem.html @@ -2,9 +2,9 @@ - + InvoiceItem - + @@ -87,16 +87,8 @@
        gr.spinellis.invoice

        Class InvoiceItem

        - - - - - - - - - -
        Package class diagram package InvoiceItem
        + +
          diff --git a/testdata/umldoc-ref/gr/spinellis/invoice/gr.spinellis.invoice.dot b/testdata/umldoc-ref/gr/spinellis/invoice/gr.spinellis.invoice.dot index 44e8280..a2ad5de 100644 --- a/testdata/umldoc-ref/gr/spinellis/invoice/gr.spinellis.invoice.dot +++ b/testdata/umldoc-ref/gr/spinellis/invoice/gr.spinellis.invoice.dot @@ -1,23 +1,23 @@ #!/usr/local/bin/dot # # Class diagram -# Generated by UMLGraph version 5.4 (http://www.umlgraph.org/) +# Generated by UMLGraph version R5_7_2-11-g86574a (http://www.umlgraph.org/) # digraph G { edge [fontname="Helvetica",fontsize=10,labelfontname="Helvetica",labelfontsize=10]; - node [fontname="Helvetica",fontsize=10,shape=plaintext]; - nodesep=0.25; - ranksep=0.5; - // gr.spinellis.invoice.InvoiceItem - c0 [label=<
          InvoiceItem
          >, URL="./InvoiceItem.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.invoice.Invoice - c1 [label=<
          Invoice
          >, URL="./Invoice.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.invoice.Customer - c2 [label=<
          Customer
          >, URL="./Customer.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; - // gr.spinellis.invoice.Invoice NAVASSOC gr.spinellis.invoice.InvoiceItem - c1:p -> c0:p [taillabel="", label="", headlabel="*", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open]; - // gr.spinellis.invoice.Invoice NAVASSOC gr.spinellis.invoice.Customer - c1:p -> c2:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open]; + node [fontname="Helvetica",fontsize=10,shape=plaintext]; + nodesep=0.25; + ranksep=0.5; + // gr.spinellis.invoice.InvoiceItem + c0 [label=<
          InvoiceItem
          >, URL="./InvoiceItem.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; + // gr.spinellis.invoice.Invoice + c1 [label=<
          Invoice
          >, URL="./Invoice.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; + // gr.spinellis.invoice.Customer + c2 [label=<
          Customer
          >, URL="./Customer.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; + // gr.spinellis.invoice.Invoice NAVASSOC gr.spinellis.invoice.InvoiceItem + c1:p -> c0:p [taillabel="", label="", headlabel="*", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open]; + // gr.spinellis.invoice.Invoice NAVASSOC gr.spinellis.invoice.Customer + c1:p -> c2:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open]; } - + diff --git a/testdata/umldoc-ref/gr/spinellis/invoice/package-frame.html b/testdata/umldoc-ref/gr/spinellis/invoice/package-frame.html index 921b144..d5b4092 100644 --- a/testdata/umldoc-ref/gr/spinellis/invoice/package-frame.html +++ b/testdata/umldoc-ref/gr/spinellis/invoice/package-frame.html @@ -2,9 +2,9 @@ - + gr.spinellis.invoice - + diff --git a/testdata/umldoc-ref/gr/spinellis/invoice/package-summary.html b/testdata/umldoc-ref/gr/spinellis/invoice/package-summary.html index cdd36ba..2ee10ac 100644 --- a/testdata/umldoc-ref/gr/spinellis/invoice/package-summary.html +++ b/testdata/umldoc-ref/gr/spinellis/invoice/package-summary.html @@ -2,9 +2,9 @@ - + gr.spinellis.invoice - + @@ -70,16 +70,8 @@

          Package gr.spinellis.invoice

          - - - - - - - - - -
          Package class diagram package gr.spinellis.invoice
          + +
            diff --git a/testdata/umldoc-ref/gr/spinellis/invoice/package-tree.html b/testdata/umldoc-ref/gr/spinellis/invoice/package-tree.html index c9b4ea9..cac2ec7 100644 --- a/testdata/umldoc-ref/gr/spinellis/invoice/package-tree.html +++ b/testdata/umldoc-ref/gr/spinellis/invoice/package-tree.html @@ -2,9 +2,9 @@ - + gr.spinellis.invoice Class Hierarchy - + diff --git a/testdata/umldoc-ref/gr/spinellis/product/Category.dot b/testdata/umldoc-ref/gr/spinellis/product/Category.dot index 0e45cb1..94aa1d1 100644 --- a/testdata/umldoc-ref/gr/spinellis/product/Category.dot +++ b/testdata/umldoc-ref/gr/spinellis/product/Category.dot @@ -1,7 +1,7 @@ #!/usr/local/bin/dot # # Class diagram -# Generated by UMLGraph version R5_7_0-10-g786d98 (http://www.umlgraph.org/) +# Generated by UMLGraph version R5_7_2-11-g86574a (http://www.umlgraph.org/) # digraph G { @@ -10,9 +10,9 @@ digraph G { nodesep=0.25; ranksep=0.5; // gr.spinellis.product.Product - c20 [label=<
            Product
            >, URL="./Product.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; + c20 [label=<
            Product
            >, URL="./Product.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; // gr.spinellis.product.Category - c21 [label=<
            Category
            >, URL="./Category.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; + c21 [label=<
            Category
            >, URL="./Category.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; // gr.spinellis.product.Product NAVASSOC java.lang.String c20:p -> c27:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open]; // gr.spinellis.product.Product NAVASSOC gr.spinellis.product.Category @@ -20,6 +20,6 @@ digraph G { // gr.spinellis.product.Category NAVASSOC java.lang.String c21:p -> c27:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open]; // java.lang.String - c27 [label=<
            String
            java.lang
            >, URL="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/String.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; + c27 [label=<
            String
            java.lang
            >, URL="http://docs.oracle.com/javase/7/docs/api/java/lang/String.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; } diff --git a/testdata/umldoc-ref/gr/spinellis/product/Category.html b/testdata/umldoc-ref/gr/spinellis/product/Category.html index 63c034a..1e5c227 100644 --- a/testdata/umldoc-ref/gr/spinellis/product/Category.html +++ b/testdata/umldoc-ref/gr/spinellis/product/Category.html @@ -2,9 +2,9 @@ - + Category - + @@ -87,16 +87,8 @@
            gr.spinellis.product

            Class Category

            - - - - - - - - - -
            Package class diagram package Category
            + +
              diff --git a/testdata/umldoc-ref/gr/spinellis/product/Product.dot b/testdata/umldoc-ref/gr/spinellis/product/Product.dot index 0f756b1..e34b4d9 100644 --- a/testdata/umldoc-ref/gr/spinellis/product/Product.dot +++ b/testdata/umldoc-ref/gr/spinellis/product/Product.dot @@ -1,7 +1,7 @@ #!/usr/local/bin/dot # # Class diagram -# Generated by UMLGraph version R5_7_0-10-g786d98 (http://www.umlgraph.org/) +# Generated by UMLGraph version R5_7_2-11-g86574a (http://www.umlgraph.org/) # digraph G { @@ -10,13 +10,13 @@ digraph G { nodesep=0.25; ranksep=0.5; // gr.spinellis.invoice.InvoiceItem - c56 [label=<
              InvoiceItem
              gr.spinellis.invoice
              >, URL="../invoice/InvoiceItem.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; + c56 [label=<
              InvoiceItem
              gr.spinellis.invoice
              >, URL="../invoice/InvoiceItem.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; // gr.spinellis.invoice.Invoice - c57 [label=<
              Invoice
              gr.spinellis.invoice
              >, URL="../invoice/Invoice.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; + c57 [label=<
              Invoice
              gr.spinellis.invoice
              >, URL="../invoice/Invoice.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; // gr.spinellis.product.Product - c59 [label=<
              Product
              >, URL="./Product.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; + c59 [label=<
              Product
              >, URL="./Product.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; // gr.spinellis.product.Category - c60 [label=<
              Category
              >, URL="./Category.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; + c60 [label=<
              Category
              >, URL="./Category.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; // gr.spinellis.invoice.InvoiceItem NAVASSOC gr.spinellis.product.Product c56:p -> c59:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open]; // gr.spinellis.invoice.Invoice NAVASSOC gr.spinellis.invoice.InvoiceItem @@ -30,6 +30,6 @@ digraph G { // gr.spinellis.invoice.Invoice DEPEND gr.spinellis.product.Product c57:p -> c59:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open, style=dashed]; // java.lang.String - c61 [label=<
              String
              java.lang
              >, URL="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/String.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; + c61 [label=<
              String
              java.lang
              >, URL="http://docs.oracle.com/javase/7/docs/api/java/lang/String.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; } diff --git a/testdata/umldoc-ref/gr/spinellis/product/Product.html b/testdata/umldoc-ref/gr/spinellis/product/Product.html index 42dbb65..47ffa0f 100644 --- a/testdata/umldoc-ref/gr/spinellis/product/Product.html +++ b/testdata/umldoc-ref/gr/spinellis/product/Product.html @@ -2,9 +2,9 @@ - + Product - + @@ -87,20 +87,8 @@
              gr.spinellis.product

              Class Product

              - - - - - - - - - - - - - -
              Package class diagram package Product
              + +
                diff --git a/testdata/umldoc-ref/gr/spinellis/product/gr.spinellis.product.dot b/testdata/umldoc-ref/gr/spinellis/product/gr.spinellis.product.dot index a1e9f6d..04606aa 100644 --- a/testdata/umldoc-ref/gr/spinellis/product/gr.spinellis.product.dot +++ b/testdata/umldoc-ref/gr/spinellis/product/gr.spinellis.product.dot @@ -1,7 +1,7 @@ #!/usr/local/bin/dot # # Class diagram -# Generated by UMLGraph version R5_7_0-10-g786d98 (http://www.umlgraph.org/) +# Generated by UMLGraph version R5_7_2-11-g86574a (http://www.umlgraph.org/) # digraph G { @@ -10,9 +10,9 @@ digraph G { nodesep=0.25; ranksep=0.5; // gr.spinellis.product.Product - c8 [label=<
                Product
                >, URL="./Product.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; + c8 [label=<
                Product
                >, URL="./Product.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; // gr.spinellis.product.Category - c9 [label=<
                Category
                >, URL="./Category.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; + c9 [label=<
                Category
                >, URL="./Category.html", fontname="Helvetica", fontcolor="black", fontsize=10.0]; // gr.spinellis.product.Product NAVASSOC gr.spinellis.product.Category c8:p -> c9:p [taillabel="", label="", headlabel="", fontname="Helvetica", fontcolor="black", fontsize=10.0, color="black", arrowhead=open]; } diff --git a/testdata/umldoc-ref/gr/spinellis/product/package-frame.html b/testdata/umldoc-ref/gr/spinellis/product/package-frame.html index ac90d4e..1704070 100644 --- a/testdata/umldoc-ref/gr/spinellis/product/package-frame.html +++ b/testdata/umldoc-ref/gr/spinellis/product/package-frame.html @@ -2,9 +2,9 @@ - + gr.spinellis.product - + diff --git a/testdata/umldoc-ref/gr/spinellis/product/package-summary.html b/testdata/umldoc-ref/gr/spinellis/product/package-summary.html index 38a8409..3c33e0c 100644 --- a/testdata/umldoc-ref/gr/spinellis/product/package-summary.html +++ b/testdata/umldoc-ref/gr/spinellis/product/package-summary.html @@ -2,9 +2,9 @@ - + gr.spinellis.product - + @@ -70,14 +70,8 @@

                Package gr.spinellis.product

                - - - - - - - -
                Package class diagram package gr.spinellis.product
                + +
                  diff --git a/testdata/umldoc-ref/gr/spinellis/product/package-tree.html b/testdata/umldoc-ref/gr/spinellis/product/package-tree.html index 8fcbdce..ac6f159 100644 --- a/testdata/umldoc-ref/gr/spinellis/product/package-tree.html +++ b/testdata/umldoc-ref/gr/spinellis/product/package-tree.html @@ -2,9 +2,9 @@ - + gr.spinellis.product Class Hierarchy - + diff --git a/testdata/umldoc-ref/help-doc.html b/testdata/umldoc-ref/help-doc.html index c56e4a1..101fc14 100644 --- a/testdata/umldoc-ref/help-doc.html +++ b/testdata/umldoc-ref/help-doc.html @@ -2,9 +2,9 @@ - + API Help - + diff --git a/testdata/umldoc-ref/index-all.html b/testdata/umldoc-ref/index-all.html index ab1cb74..09fed8e 100644 --- a/testdata/umldoc-ref/index-all.html +++ b/testdata/umldoc-ref/index-all.html @@ -2,9 +2,9 @@ - + Index - + diff --git a/testdata/umldoc-ref/index.html b/testdata/umldoc-ref/index.html index dbd743a..fd41127 100644 --- a/testdata/umldoc-ref/index.html +++ b/testdata/umldoc-ref/index.html @@ -2,14 +2,15 @@ - + Generated Documentation (Untitled) diff --git a/testdata/umldoc-ref/overview-summary.html b/testdata/umldoc-ref/overview-summary.html index 442672b..6128cde 100644 --- a/testdata/umldoc-ref/overview-summary.html +++ b/testdata/umldoc-ref/overview-summary.html @@ -2,9 +2,9 @@ - + Overview - + diff --git a/testdata/umldoc-ref/overview-tree.html b/testdata/umldoc-ref/overview-tree.html index f40f7bc..d3a767b 100644 --- a/testdata/umldoc-ref/overview-tree.html +++ b/testdata/umldoc-ref/overview-tree.html @@ -2,9 +2,9 @@ - + Class Hierarchy - + diff --git a/umlgraph b/umlgraph index 2119ace..71794b0 100755 --- a/umlgraph +++ b/umlgraph @@ -8,6 +8,13 @@ UMLGRAPH_HOME=lib +# Obtain a classpath path separator that works for Unix and Cygwin +if expr "$JAVA_HOME" : '.*:' >/dev/null ; then + CPS=';' +else + CPS=':' +fi + if [ x$2 = x ] then echo usage: umlgraph base_file_name filetype [umlgraph arguments] 1>&2 @@ -18,7 +25,7 @@ else BASE=$1 FILETYPE=$2 shift 2 - java -classpath "$UMLGRAPH_HOME/UmlGraph.jar:$JAVA_HOME/lib/tools.jar" \ + java -classpath "$UMLGRAPH_HOME/UmlGraph.jar${CPS}$JAVA_HOME/lib/tools.jar" \ org.umlgraph.doclet.UmlGraph -package $* -output - $BASE.java | dot -T$FILETYPE -o$BASE.$FILETYPE fi diff --git a/web/index.html b/web/index.html index 21d4e8d..1956959 100644 --- a/web/index.html +++ b/web/index.html @@ -10,7 +10,7 @@ all types UML diagrams. An IEEE Software article titled On the declarative specification of models explains the rationale behind this approach. -The tehnology behind UMLGraph was used to draw many of the diagrams +The technology behind UMLGraph was used to draw many of the diagrams appearing in the award-winning books Code Quality: The Open Source Perspective (Addison Wesley, 2006) and Code Reading: The Open Source Perspective (Addison Wesley, 2003).