From 7ae270fdda9c412d9ab01266a29ee3ad2b1ed94b Mon Sep 17 00:00:00 2001 From: Diomidis Spinellis Date: Fri, 26 Jul 2002 11:28:53 +0000 Subject: [PATCH] Model aggregation and composition relationships. --- .../spinellis/umlgraph/doclet/ClassGraph.java | 101 ++++++++++++++++-- .../spinellis/umlgraph/doclet/ClassInfo.java | 101 ++++++++++++++++-- src/gr/spinellis/umlgraph/doclet/Options.java | 101 ++++++++++++++++-- .../spinellis/umlgraph/doclet/StringUtil.java | 101 ++++++++++++++++-- .../spinellis/umlgraph/doclet/UmlGraph.java | 101 ++++++++++++++++-- src/org/umlgraph/doclet/ClassGraph.java | 101 ++++++++++++++++-- src/org/umlgraph/doclet/ClassInfo.java | 101 ++++++++++++++++-- src/org/umlgraph/doclet/Options.java | 101 ++++++++++++++++-- src/org/umlgraph/doclet/StringUtil.java | 101 ++++++++++++++++-- src/org/umlgraph/doclet/UmlGraph.java | 101 ++++++++++++++++-- 10 files changed, 900 insertions(+), 110 deletions(-) diff --git a/src/gr/spinellis/umlgraph/doclet/ClassGraph.java b/src/gr/spinellis/umlgraph/doclet/ClassGraph.java index 4fe564e..49466bc 100644 --- a/src/gr/spinellis/umlgraph/doclet/ClassGraph.java +++ b/src/gr/spinellis/umlgraph/doclet/ClassGraph.java @@ -52,10 +52,23 @@ class Options { } } +class ClassInfo { + private static int classnum; + /** Alias name for the class */ + String name; + /** True if the class class node has been printed */ + boolean nodePrinted; + + ClassInfo(boolean p) { + nodePrinted = p; + name = "c" + (new Integer(classnum)).toString(); + classnum++; + } +} + class ClassGraph { private ClassDoc c; private static HashMap classnames = new HashMap(); - private static int classnum; private Options opt; ClassGraph(Options iopt, ClassDoc ic) { @@ -118,14 +131,26 @@ class ClassGraph { } } - private String name(ClassDoc c) { - String name; + private String name(String c) { + ClassInfo ci; - if ((name = (String)classnames.get(c)) == null) { + if ((ci = (ClassInfo)classnames.get(c)) == null) + classnames.put(c, ci = new ClassInfo(false)); + return ci.name; + } + + private String name(ClassDoc c) { + ClassInfo ci; + boolean toPrint; + + if ((ci = (ClassInfo)classnames.get(c.toString())) != null) + toPrint = !ci.nodePrinted; + else { + toPrint = true; + classnames.put(c, ci = new ClassInfo(true)); + } + if (toPrint) { // Associate classnames alias - name = "c" + (new Integer(classnum)).toString(); - classnames.put(c, name); - classnum++; String r = c.toString(); if (!opt.showQualified) { // Create readable string by stripping leading path @@ -134,7 +159,7 @@ class ClassGraph { r = r.substring(dotpos + 1, r.length()); } // Create label - opt.w.print("\t" + name + " ["); + opt.w.print("\t" + ci.name + " ["); if (opt.showAttributes || opt.showOperations) opt.w.print("label=\"{" + r + "\\n|"); else @@ -151,23 +176,75 @@ class ClassGraph { opt.w.print(", fontname=\"Helvetica-Oblique\""); opt.w.println("];"); } - return name; + return ci.name; + } + + private String[] tokenize(String s) { + String r[] = new String[4]; + String remain = s, tok; + int n = 0, pos; + + remain.trim(); + while (remain.length() > 0 && n < 4) { + if (remain.startsWith("\"")) { + // Field in quotes + pos = remain.indexOf('"', 1); + if (pos == -1) + break; + r[n] = remain.substring(1, pos); + if (pos + 1 < remain.length()) + pos++; + } else { + // Space-separated field + pos = remain.indexOf(' ', 0); + if (pos == -1) + r[n] = remain; + else + r[n] = remain.substring(0, pos); + } + remain = remain.substring(pos + 1); + remain.trim(); + // - is used as a placeholder for empy fields + if (r[n].equals("-")) + r[n] = ""; + n++; + } + if (n != 4) + System.err.println("Expected four fields: " + s); + return (r); + } + + private void relation(String tagname, Doc from, String name, String edgetype) { + Tag tags[] = from.tags(tagname); + for (int i = 0; i < tags.length; i++) { + String t[] = tokenize(tags[i].text()); // l-src label l-dst target + opt.w.println("\t" + name + " -> " + name(t[3]) + "[" + + "taillabel=\"" + t[0] + "\", " + + "label=\"" + t[1] + "\", " + + "headlabel=\"" + t[2] + "\", " + + edgetype + "]" + ); + } } public void print() { String cs = name(c); - // Print the derivation path + // Print generalization (through the Java superclass) ClassDoc s = c.superclass(); if (s != null && !s.toString().equals("java.lang.Object")) { opt.w.print("\t" + name(s) + " -> " + cs + " [dir=back,arrowtail=empty];"); opt.w.println("\t//" + c + " extends " + s); } - // Print interfaces + // Print realizations (Java interfaces) ClassDoc ifs[] = c.interfaces(); for (int i = 0; i < ifs.length; i++) { opt.w.print("\t" + name(ifs[i]) + " -> " + cs + " [dir=back,arrowtail=empty,style=dashed];"); opt.w.println("\t//" + c + " implements " + s); } + // Print associations + relation("assoc", c, cs, "arrowhead=none"); + relation("has", c, cs, "arrowhead=none, arrowtail=ediamond"); + relation("composed", c, cs, "arrowhead=none, arrowtail=diamond"); } } @@ -223,6 +300,8 @@ public class UmlGraph { "# Generated by $Id$\n" + "#\n\n" + "digraph G {\n" + + "edge [fontname=\"Helvetica\",fontsize=8,labelfontname=\"Helvetica\",labelfontsize=8];\n" + + "\tnode [fontname=\"Helvetica\",fontsize=8,shape=record];" ); } diff --git a/src/gr/spinellis/umlgraph/doclet/ClassInfo.java b/src/gr/spinellis/umlgraph/doclet/ClassInfo.java index 4fe564e..49466bc 100644 --- a/src/gr/spinellis/umlgraph/doclet/ClassInfo.java +++ b/src/gr/spinellis/umlgraph/doclet/ClassInfo.java @@ -52,10 +52,23 @@ class Options { } } +class ClassInfo { + private static int classnum; + /** Alias name for the class */ + String name; + /** True if the class class node has been printed */ + boolean nodePrinted; + + ClassInfo(boolean p) { + nodePrinted = p; + name = "c" + (new Integer(classnum)).toString(); + classnum++; + } +} + class ClassGraph { private ClassDoc c; private static HashMap classnames = new HashMap(); - private static int classnum; private Options opt; ClassGraph(Options iopt, ClassDoc ic) { @@ -118,14 +131,26 @@ class ClassGraph { } } - private String name(ClassDoc c) { - String name; + private String name(String c) { + ClassInfo ci; - if ((name = (String)classnames.get(c)) == null) { + if ((ci = (ClassInfo)classnames.get(c)) == null) + classnames.put(c, ci = new ClassInfo(false)); + return ci.name; + } + + private String name(ClassDoc c) { + ClassInfo ci; + boolean toPrint; + + if ((ci = (ClassInfo)classnames.get(c.toString())) != null) + toPrint = !ci.nodePrinted; + else { + toPrint = true; + classnames.put(c, ci = new ClassInfo(true)); + } + if (toPrint) { // Associate classnames alias - name = "c" + (new Integer(classnum)).toString(); - classnames.put(c, name); - classnum++; String r = c.toString(); if (!opt.showQualified) { // Create readable string by stripping leading path @@ -134,7 +159,7 @@ class ClassGraph { r = r.substring(dotpos + 1, r.length()); } // Create label - opt.w.print("\t" + name + " ["); + opt.w.print("\t" + ci.name + " ["); if (opt.showAttributes || opt.showOperations) opt.w.print("label=\"{" + r + "\\n|"); else @@ -151,23 +176,75 @@ class ClassGraph { opt.w.print(", fontname=\"Helvetica-Oblique\""); opt.w.println("];"); } - return name; + return ci.name; + } + + private String[] tokenize(String s) { + String r[] = new String[4]; + String remain = s, tok; + int n = 0, pos; + + remain.trim(); + while (remain.length() > 0 && n < 4) { + if (remain.startsWith("\"")) { + // Field in quotes + pos = remain.indexOf('"', 1); + if (pos == -1) + break; + r[n] = remain.substring(1, pos); + if (pos + 1 < remain.length()) + pos++; + } else { + // Space-separated field + pos = remain.indexOf(' ', 0); + if (pos == -1) + r[n] = remain; + else + r[n] = remain.substring(0, pos); + } + remain = remain.substring(pos + 1); + remain.trim(); + // - is used as a placeholder for empy fields + if (r[n].equals("-")) + r[n] = ""; + n++; + } + if (n != 4) + System.err.println("Expected four fields: " + s); + return (r); + } + + private void relation(String tagname, Doc from, String name, String edgetype) { + Tag tags[] = from.tags(tagname); + for (int i = 0; i < tags.length; i++) { + String t[] = tokenize(tags[i].text()); // l-src label l-dst target + opt.w.println("\t" + name + " -> " + name(t[3]) + "[" + + "taillabel=\"" + t[0] + "\", " + + "label=\"" + t[1] + "\", " + + "headlabel=\"" + t[2] + "\", " + + edgetype + "]" + ); + } } public void print() { String cs = name(c); - // Print the derivation path + // Print generalization (through the Java superclass) ClassDoc s = c.superclass(); if (s != null && !s.toString().equals("java.lang.Object")) { opt.w.print("\t" + name(s) + " -> " + cs + " [dir=back,arrowtail=empty];"); opt.w.println("\t//" + c + " extends " + s); } - // Print interfaces + // Print realizations (Java interfaces) ClassDoc ifs[] = c.interfaces(); for (int i = 0; i < ifs.length; i++) { opt.w.print("\t" + name(ifs[i]) + " -> " + cs + " [dir=back,arrowtail=empty,style=dashed];"); opt.w.println("\t//" + c + " implements " + s); } + // Print associations + relation("assoc", c, cs, "arrowhead=none"); + relation("has", c, cs, "arrowhead=none, arrowtail=ediamond"); + relation("composed", c, cs, "arrowhead=none, arrowtail=diamond"); } } @@ -223,6 +300,8 @@ public class UmlGraph { "# Generated by $Id$\n" + "#\n\n" + "digraph G {\n" + + "edge [fontname=\"Helvetica\",fontsize=8,labelfontname=\"Helvetica\",labelfontsize=8];\n" + + "\tnode [fontname=\"Helvetica\",fontsize=8,shape=record];" ); } diff --git a/src/gr/spinellis/umlgraph/doclet/Options.java b/src/gr/spinellis/umlgraph/doclet/Options.java index 4fe564e..49466bc 100644 --- a/src/gr/spinellis/umlgraph/doclet/Options.java +++ b/src/gr/spinellis/umlgraph/doclet/Options.java @@ -52,10 +52,23 @@ class Options { } } +class ClassInfo { + private static int classnum; + /** Alias name for the class */ + String name; + /** True if the class class node has been printed */ + boolean nodePrinted; + + ClassInfo(boolean p) { + nodePrinted = p; + name = "c" + (new Integer(classnum)).toString(); + classnum++; + } +} + class ClassGraph { private ClassDoc c; private static HashMap classnames = new HashMap(); - private static int classnum; private Options opt; ClassGraph(Options iopt, ClassDoc ic) { @@ -118,14 +131,26 @@ class ClassGraph { } } - private String name(ClassDoc c) { - String name; + private String name(String c) { + ClassInfo ci; - if ((name = (String)classnames.get(c)) == null) { + if ((ci = (ClassInfo)classnames.get(c)) == null) + classnames.put(c, ci = new ClassInfo(false)); + return ci.name; + } + + private String name(ClassDoc c) { + ClassInfo ci; + boolean toPrint; + + if ((ci = (ClassInfo)classnames.get(c.toString())) != null) + toPrint = !ci.nodePrinted; + else { + toPrint = true; + classnames.put(c, ci = new ClassInfo(true)); + } + if (toPrint) { // Associate classnames alias - name = "c" + (new Integer(classnum)).toString(); - classnames.put(c, name); - classnum++; String r = c.toString(); if (!opt.showQualified) { // Create readable string by stripping leading path @@ -134,7 +159,7 @@ class ClassGraph { r = r.substring(dotpos + 1, r.length()); } // Create label - opt.w.print("\t" + name + " ["); + opt.w.print("\t" + ci.name + " ["); if (opt.showAttributes || opt.showOperations) opt.w.print("label=\"{" + r + "\\n|"); else @@ -151,23 +176,75 @@ class ClassGraph { opt.w.print(", fontname=\"Helvetica-Oblique\""); opt.w.println("];"); } - return name; + return ci.name; + } + + private String[] tokenize(String s) { + String r[] = new String[4]; + String remain = s, tok; + int n = 0, pos; + + remain.trim(); + while (remain.length() > 0 && n < 4) { + if (remain.startsWith("\"")) { + // Field in quotes + pos = remain.indexOf('"', 1); + if (pos == -1) + break; + r[n] = remain.substring(1, pos); + if (pos + 1 < remain.length()) + pos++; + } else { + // Space-separated field + pos = remain.indexOf(' ', 0); + if (pos == -1) + r[n] = remain; + else + r[n] = remain.substring(0, pos); + } + remain = remain.substring(pos + 1); + remain.trim(); + // - is used as a placeholder for empy fields + if (r[n].equals("-")) + r[n] = ""; + n++; + } + if (n != 4) + System.err.println("Expected four fields: " + s); + return (r); + } + + private void relation(String tagname, Doc from, String name, String edgetype) { + Tag tags[] = from.tags(tagname); + for (int i = 0; i < tags.length; i++) { + String t[] = tokenize(tags[i].text()); // l-src label l-dst target + opt.w.println("\t" + name + " -> " + name(t[3]) + "[" + + "taillabel=\"" + t[0] + "\", " + + "label=\"" + t[1] + "\", " + + "headlabel=\"" + t[2] + "\", " + + edgetype + "]" + ); + } } public void print() { String cs = name(c); - // Print the derivation path + // Print generalization (through the Java superclass) ClassDoc s = c.superclass(); if (s != null && !s.toString().equals("java.lang.Object")) { opt.w.print("\t" + name(s) + " -> " + cs + " [dir=back,arrowtail=empty];"); opt.w.println("\t//" + c + " extends " + s); } - // Print interfaces + // Print realizations (Java interfaces) ClassDoc ifs[] = c.interfaces(); for (int i = 0; i < ifs.length; i++) { opt.w.print("\t" + name(ifs[i]) + " -> " + cs + " [dir=back,arrowtail=empty,style=dashed];"); opt.w.println("\t//" + c + " implements " + s); } + // Print associations + relation("assoc", c, cs, "arrowhead=none"); + relation("has", c, cs, "arrowhead=none, arrowtail=ediamond"); + relation("composed", c, cs, "arrowhead=none, arrowtail=diamond"); } } @@ -223,6 +300,8 @@ public class UmlGraph { "# Generated by $Id$\n" + "#\n\n" + "digraph G {\n" + + "edge [fontname=\"Helvetica\",fontsize=8,labelfontname=\"Helvetica\",labelfontsize=8];\n" + + "\tnode [fontname=\"Helvetica\",fontsize=8,shape=record];" ); } diff --git a/src/gr/spinellis/umlgraph/doclet/StringUtil.java b/src/gr/spinellis/umlgraph/doclet/StringUtil.java index 4fe564e..49466bc 100644 --- a/src/gr/spinellis/umlgraph/doclet/StringUtil.java +++ b/src/gr/spinellis/umlgraph/doclet/StringUtil.java @@ -52,10 +52,23 @@ class Options { } } +class ClassInfo { + private static int classnum; + /** Alias name for the class */ + String name; + /** True if the class class node has been printed */ + boolean nodePrinted; + + ClassInfo(boolean p) { + nodePrinted = p; + name = "c" + (new Integer(classnum)).toString(); + classnum++; + } +} + class ClassGraph { private ClassDoc c; private static HashMap classnames = new HashMap(); - private static int classnum; private Options opt; ClassGraph(Options iopt, ClassDoc ic) { @@ -118,14 +131,26 @@ class ClassGraph { } } - private String name(ClassDoc c) { - String name; + private String name(String c) { + ClassInfo ci; - if ((name = (String)classnames.get(c)) == null) { + if ((ci = (ClassInfo)classnames.get(c)) == null) + classnames.put(c, ci = new ClassInfo(false)); + return ci.name; + } + + private String name(ClassDoc c) { + ClassInfo ci; + boolean toPrint; + + if ((ci = (ClassInfo)classnames.get(c.toString())) != null) + toPrint = !ci.nodePrinted; + else { + toPrint = true; + classnames.put(c, ci = new ClassInfo(true)); + } + if (toPrint) { // Associate classnames alias - name = "c" + (new Integer(classnum)).toString(); - classnames.put(c, name); - classnum++; String r = c.toString(); if (!opt.showQualified) { // Create readable string by stripping leading path @@ -134,7 +159,7 @@ class ClassGraph { r = r.substring(dotpos + 1, r.length()); } // Create label - opt.w.print("\t" + name + " ["); + opt.w.print("\t" + ci.name + " ["); if (opt.showAttributes || opt.showOperations) opt.w.print("label=\"{" + r + "\\n|"); else @@ -151,23 +176,75 @@ class ClassGraph { opt.w.print(", fontname=\"Helvetica-Oblique\""); opt.w.println("];"); } - return name; + return ci.name; + } + + private String[] tokenize(String s) { + String r[] = new String[4]; + String remain = s, tok; + int n = 0, pos; + + remain.trim(); + while (remain.length() > 0 && n < 4) { + if (remain.startsWith("\"")) { + // Field in quotes + pos = remain.indexOf('"', 1); + if (pos == -1) + break; + r[n] = remain.substring(1, pos); + if (pos + 1 < remain.length()) + pos++; + } else { + // Space-separated field + pos = remain.indexOf(' ', 0); + if (pos == -1) + r[n] = remain; + else + r[n] = remain.substring(0, pos); + } + remain = remain.substring(pos + 1); + remain.trim(); + // - is used as a placeholder for empy fields + if (r[n].equals("-")) + r[n] = ""; + n++; + } + if (n != 4) + System.err.println("Expected four fields: " + s); + return (r); + } + + private void relation(String tagname, Doc from, String name, String edgetype) { + Tag tags[] = from.tags(tagname); + for (int i = 0; i < tags.length; i++) { + String t[] = tokenize(tags[i].text()); // l-src label l-dst target + opt.w.println("\t" + name + " -> " + name(t[3]) + "[" + + "taillabel=\"" + t[0] + "\", " + + "label=\"" + t[1] + "\", " + + "headlabel=\"" + t[2] + "\", " + + edgetype + "]" + ); + } } public void print() { String cs = name(c); - // Print the derivation path + // Print generalization (through the Java superclass) ClassDoc s = c.superclass(); if (s != null && !s.toString().equals("java.lang.Object")) { opt.w.print("\t" + name(s) + " -> " + cs + " [dir=back,arrowtail=empty];"); opt.w.println("\t//" + c + " extends " + s); } - // Print interfaces + // Print realizations (Java interfaces) ClassDoc ifs[] = c.interfaces(); for (int i = 0; i < ifs.length; i++) { opt.w.print("\t" + name(ifs[i]) + " -> " + cs + " [dir=back,arrowtail=empty,style=dashed];"); opt.w.println("\t//" + c + " implements " + s); } + // Print associations + relation("assoc", c, cs, "arrowhead=none"); + relation("has", c, cs, "arrowhead=none, arrowtail=ediamond"); + relation("composed", c, cs, "arrowhead=none, arrowtail=diamond"); } } @@ -223,6 +300,8 @@ public class UmlGraph { "# Generated by $Id$\n" + "#\n\n" + "digraph G {\n" + + "edge [fontname=\"Helvetica\",fontsize=8,labelfontname=\"Helvetica\",labelfontsize=8];\n" + + "\tnode [fontname=\"Helvetica\",fontsize=8,shape=record];" ); } diff --git a/src/gr/spinellis/umlgraph/doclet/UmlGraph.java b/src/gr/spinellis/umlgraph/doclet/UmlGraph.java index 4fe564e..49466bc 100644 --- a/src/gr/spinellis/umlgraph/doclet/UmlGraph.java +++ b/src/gr/spinellis/umlgraph/doclet/UmlGraph.java @@ -52,10 +52,23 @@ class Options { } } +class ClassInfo { + private static int classnum; + /** Alias name for the class */ + String name; + /** True if the class class node has been printed */ + boolean nodePrinted; + + ClassInfo(boolean p) { + nodePrinted = p; + name = "c" + (new Integer(classnum)).toString(); + classnum++; + } +} + class ClassGraph { private ClassDoc c; private static HashMap classnames = new HashMap(); - private static int classnum; private Options opt; ClassGraph(Options iopt, ClassDoc ic) { @@ -118,14 +131,26 @@ class ClassGraph { } } - private String name(ClassDoc c) { - String name; + private String name(String c) { + ClassInfo ci; - if ((name = (String)classnames.get(c)) == null) { + if ((ci = (ClassInfo)classnames.get(c)) == null) + classnames.put(c, ci = new ClassInfo(false)); + return ci.name; + } + + private String name(ClassDoc c) { + ClassInfo ci; + boolean toPrint; + + if ((ci = (ClassInfo)classnames.get(c.toString())) != null) + toPrint = !ci.nodePrinted; + else { + toPrint = true; + classnames.put(c, ci = new ClassInfo(true)); + } + if (toPrint) { // Associate classnames alias - name = "c" + (new Integer(classnum)).toString(); - classnames.put(c, name); - classnum++; String r = c.toString(); if (!opt.showQualified) { // Create readable string by stripping leading path @@ -134,7 +159,7 @@ class ClassGraph { r = r.substring(dotpos + 1, r.length()); } // Create label - opt.w.print("\t" + name + " ["); + opt.w.print("\t" + ci.name + " ["); if (opt.showAttributes || opt.showOperations) opt.w.print("label=\"{" + r + "\\n|"); else @@ -151,23 +176,75 @@ class ClassGraph { opt.w.print(", fontname=\"Helvetica-Oblique\""); opt.w.println("];"); } - return name; + return ci.name; + } + + private String[] tokenize(String s) { + String r[] = new String[4]; + String remain = s, tok; + int n = 0, pos; + + remain.trim(); + while (remain.length() > 0 && n < 4) { + if (remain.startsWith("\"")) { + // Field in quotes + pos = remain.indexOf('"', 1); + if (pos == -1) + break; + r[n] = remain.substring(1, pos); + if (pos + 1 < remain.length()) + pos++; + } else { + // Space-separated field + pos = remain.indexOf(' ', 0); + if (pos == -1) + r[n] = remain; + else + r[n] = remain.substring(0, pos); + } + remain = remain.substring(pos + 1); + remain.trim(); + // - is used as a placeholder for empy fields + if (r[n].equals("-")) + r[n] = ""; + n++; + } + if (n != 4) + System.err.println("Expected four fields: " + s); + return (r); + } + + private void relation(String tagname, Doc from, String name, String edgetype) { + Tag tags[] = from.tags(tagname); + for (int i = 0; i < tags.length; i++) { + String t[] = tokenize(tags[i].text()); // l-src label l-dst target + opt.w.println("\t" + name + " -> " + name(t[3]) + "[" + + "taillabel=\"" + t[0] + "\", " + + "label=\"" + t[1] + "\", " + + "headlabel=\"" + t[2] + "\", " + + edgetype + "]" + ); + } } public void print() { String cs = name(c); - // Print the derivation path + // Print generalization (through the Java superclass) ClassDoc s = c.superclass(); if (s != null && !s.toString().equals("java.lang.Object")) { opt.w.print("\t" + name(s) + " -> " + cs + " [dir=back,arrowtail=empty];"); opt.w.println("\t//" + c + " extends " + s); } - // Print interfaces + // Print realizations (Java interfaces) ClassDoc ifs[] = c.interfaces(); for (int i = 0; i < ifs.length; i++) { opt.w.print("\t" + name(ifs[i]) + " -> " + cs + " [dir=back,arrowtail=empty,style=dashed];"); opt.w.println("\t//" + c + " implements " + s); } + // Print associations + relation("assoc", c, cs, "arrowhead=none"); + relation("has", c, cs, "arrowhead=none, arrowtail=ediamond"); + relation("composed", c, cs, "arrowhead=none, arrowtail=diamond"); } } @@ -223,6 +300,8 @@ public class UmlGraph { "# Generated by $Id$\n" + "#\n\n" + "digraph G {\n" + + "edge [fontname=\"Helvetica\",fontsize=8,labelfontname=\"Helvetica\",labelfontsize=8];\n" + + "\tnode [fontname=\"Helvetica\",fontsize=8,shape=record];" ); } diff --git a/src/org/umlgraph/doclet/ClassGraph.java b/src/org/umlgraph/doclet/ClassGraph.java index 4fe564e..49466bc 100644 --- a/src/org/umlgraph/doclet/ClassGraph.java +++ b/src/org/umlgraph/doclet/ClassGraph.java @@ -52,10 +52,23 @@ class Options { } } +class ClassInfo { + private static int classnum; + /** Alias name for the class */ + String name; + /** True if the class class node has been printed */ + boolean nodePrinted; + + ClassInfo(boolean p) { + nodePrinted = p; + name = "c" + (new Integer(classnum)).toString(); + classnum++; + } +} + class ClassGraph { private ClassDoc c; private static HashMap classnames = new HashMap(); - private static int classnum; private Options opt; ClassGraph(Options iopt, ClassDoc ic) { @@ -118,14 +131,26 @@ class ClassGraph { } } - private String name(ClassDoc c) { - String name; + private String name(String c) { + ClassInfo ci; - if ((name = (String)classnames.get(c)) == null) { + if ((ci = (ClassInfo)classnames.get(c)) == null) + classnames.put(c, ci = new ClassInfo(false)); + return ci.name; + } + + private String name(ClassDoc c) { + ClassInfo ci; + boolean toPrint; + + if ((ci = (ClassInfo)classnames.get(c.toString())) != null) + toPrint = !ci.nodePrinted; + else { + toPrint = true; + classnames.put(c, ci = new ClassInfo(true)); + } + if (toPrint) { // Associate classnames alias - name = "c" + (new Integer(classnum)).toString(); - classnames.put(c, name); - classnum++; String r = c.toString(); if (!opt.showQualified) { // Create readable string by stripping leading path @@ -134,7 +159,7 @@ class ClassGraph { r = r.substring(dotpos + 1, r.length()); } // Create label - opt.w.print("\t" + name + " ["); + opt.w.print("\t" + ci.name + " ["); if (opt.showAttributes || opt.showOperations) opt.w.print("label=\"{" + r + "\\n|"); else @@ -151,23 +176,75 @@ class ClassGraph { opt.w.print(", fontname=\"Helvetica-Oblique\""); opt.w.println("];"); } - return name; + return ci.name; + } + + private String[] tokenize(String s) { + String r[] = new String[4]; + String remain = s, tok; + int n = 0, pos; + + remain.trim(); + while (remain.length() > 0 && n < 4) { + if (remain.startsWith("\"")) { + // Field in quotes + pos = remain.indexOf('"', 1); + if (pos == -1) + break; + r[n] = remain.substring(1, pos); + if (pos + 1 < remain.length()) + pos++; + } else { + // Space-separated field + pos = remain.indexOf(' ', 0); + if (pos == -1) + r[n] = remain; + else + r[n] = remain.substring(0, pos); + } + remain = remain.substring(pos + 1); + remain.trim(); + // - is used as a placeholder for empy fields + if (r[n].equals("-")) + r[n] = ""; + n++; + } + if (n != 4) + System.err.println("Expected four fields: " + s); + return (r); + } + + private void relation(String tagname, Doc from, String name, String edgetype) { + Tag tags[] = from.tags(tagname); + for (int i = 0; i < tags.length; i++) { + String t[] = tokenize(tags[i].text()); // l-src label l-dst target + opt.w.println("\t" + name + " -> " + name(t[3]) + "[" + + "taillabel=\"" + t[0] + "\", " + + "label=\"" + t[1] + "\", " + + "headlabel=\"" + t[2] + "\", " + + edgetype + "]" + ); + } } public void print() { String cs = name(c); - // Print the derivation path + // Print generalization (through the Java superclass) ClassDoc s = c.superclass(); if (s != null && !s.toString().equals("java.lang.Object")) { opt.w.print("\t" + name(s) + " -> " + cs + " [dir=back,arrowtail=empty];"); opt.w.println("\t//" + c + " extends " + s); } - // Print interfaces + // Print realizations (Java interfaces) ClassDoc ifs[] = c.interfaces(); for (int i = 0; i < ifs.length; i++) { opt.w.print("\t" + name(ifs[i]) + " -> " + cs + " [dir=back,arrowtail=empty,style=dashed];"); opt.w.println("\t//" + c + " implements " + s); } + // Print associations + relation("assoc", c, cs, "arrowhead=none"); + relation("has", c, cs, "arrowhead=none, arrowtail=ediamond"); + relation("composed", c, cs, "arrowhead=none, arrowtail=diamond"); } } @@ -223,6 +300,8 @@ public class UmlGraph { "# Generated by $Id$\n" + "#\n\n" + "digraph G {\n" + + "edge [fontname=\"Helvetica\",fontsize=8,labelfontname=\"Helvetica\",labelfontsize=8];\n" + + "\tnode [fontname=\"Helvetica\",fontsize=8,shape=record];" ); } diff --git a/src/org/umlgraph/doclet/ClassInfo.java b/src/org/umlgraph/doclet/ClassInfo.java index 4fe564e..49466bc 100644 --- a/src/org/umlgraph/doclet/ClassInfo.java +++ b/src/org/umlgraph/doclet/ClassInfo.java @@ -52,10 +52,23 @@ class Options { } } +class ClassInfo { + private static int classnum; + /** Alias name for the class */ + String name; + /** True if the class class node has been printed */ + boolean nodePrinted; + + ClassInfo(boolean p) { + nodePrinted = p; + name = "c" + (new Integer(classnum)).toString(); + classnum++; + } +} + class ClassGraph { private ClassDoc c; private static HashMap classnames = new HashMap(); - private static int classnum; private Options opt; ClassGraph(Options iopt, ClassDoc ic) { @@ -118,14 +131,26 @@ class ClassGraph { } } - private String name(ClassDoc c) { - String name; + private String name(String c) { + ClassInfo ci; - if ((name = (String)classnames.get(c)) == null) { + if ((ci = (ClassInfo)classnames.get(c)) == null) + classnames.put(c, ci = new ClassInfo(false)); + return ci.name; + } + + private String name(ClassDoc c) { + ClassInfo ci; + boolean toPrint; + + if ((ci = (ClassInfo)classnames.get(c.toString())) != null) + toPrint = !ci.nodePrinted; + else { + toPrint = true; + classnames.put(c, ci = new ClassInfo(true)); + } + if (toPrint) { // Associate classnames alias - name = "c" + (new Integer(classnum)).toString(); - classnames.put(c, name); - classnum++; String r = c.toString(); if (!opt.showQualified) { // Create readable string by stripping leading path @@ -134,7 +159,7 @@ class ClassGraph { r = r.substring(dotpos + 1, r.length()); } // Create label - opt.w.print("\t" + name + " ["); + opt.w.print("\t" + ci.name + " ["); if (opt.showAttributes || opt.showOperations) opt.w.print("label=\"{" + r + "\\n|"); else @@ -151,23 +176,75 @@ class ClassGraph { opt.w.print(", fontname=\"Helvetica-Oblique\""); opt.w.println("];"); } - return name; + return ci.name; + } + + private String[] tokenize(String s) { + String r[] = new String[4]; + String remain = s, tok; + int n = 0, pos; + + remain.trim(); + while (remain.length() > 0 && n < 4) { + if (remain.startsWith("\"")) { + // Field in quotes + pos = remain.indexOf('"', 1); + if (pos == -1) + break; + r[n] = remain.substring(1, pos); + if (pos + 1 < remain.length()) + pos++; + } else { + // Space-separated field + pos = remain.indexOf(' ', 0); + if (pos == -1) + r[n] = remain; + else + r[n] = remain.substring(0, pos); + } + remain = remain.substring(pos + 1); + remain.trim(); + // - is used as a placeholder for empy fields + if (r[n].equals("-")) + r[n] = ""; + n++; + } + if (n != 4) + System.err.println("Expected four fields: " + s); + return (r); + } + + private void relation(String tagname, Doc from, String name, String edgetype) { + Tag tags[] = from.tags(tagname); + for (int i = 0; i < tags.length; i++) { + String t[] = tokenize(tags[i].text()); // l-src label l-dst target + opt.w.println("\t" + name + " -> " + name(t[3]) + "[" + + "taillabel=\"" + t[0] + "\", " + + "label=\"" + t[1] + "\", " + + "headlabel=\"" + t[2] + "\", " + + edgetype + "]" + ); + } } public void print() { String cs = name(c); - // Print the derivation path + // Print generalization (through the Java superclass) ClassDoc s = c.superclass(); if (s != null && !s.toString().equals("java.lang.Object")) { opt.w.print("\t" + name(s) + " -> " + cs + " [dir=back,arrowtail=empty];"); opt.w.println("\t//" + c + " extends " + s); } - // Print interfaces + // Print realizations (Java interfaces) ClassDoc ifs[] = c.interfaces(); for (int i = 0; i < ifs.length; i++) { opt.w.print("\t" + name(ifs[i]) + " -> " + cs + " [dir=back,arrowtail=empty,style=dashed];"); opt.w.println("\t//" + c + " implements " + s); } + // Print associations + relation("assoc", c, cs, "arrowhead=none"); + relation("has", c, cs, "arrowhead=none, arrowtail=ediamond"); + relation("composed", c, cs, "arrowhead=none, arrowtail=diamond"); } } @@ -223,6 +300,8 @@ public class UmlGraph { "# Generated by $Id$\n" + "#\n\n" + "digraph G {\n" + + "edge [fontname=\"Helvetica\",fontsize=8,labelfontname=\"Helvetica\",labelfontsize=8];\n" + + "\tnode [fontname=\"Helvetica\",fontsize=8,shape=record];" ); } diff --git a/src/org/umlgraph/doclet/Options.java b/src/org/umlgraph/doclet/Options.java index 4fe564e..49466bc 100644 --- a/src/org/umlgraph/doclet/Options.java +++ b/src/org/umlgraph/doclet/Options.java @@ -52,10 +52,23 @@ class Options { } } +class ClassInfo { + private static int classnum; + /** Alias name for the class */ + String name; + /** True if the class class node has been printed */ + boolean nodePrinted; + + ClassInfo(boolean p) { + nodePrinted = p; + name = "c" + (new Integer(classnum)).toString(); + classnum++; + } +} + class ClassGraph { private ClassDoc c; private static HashMap classnames = new HashMap(); - private static int classnum; private Options opt; ClassGraph(Options iopt, ClassDoc ic) { @@ -118,14 +131,26 @@ class ClassGraph { } } - private String name(ClassDoc c) { - String name; + private String name(String c) { + ClassInfo ci; - if ((name = (String)classnames.get(c)) == null) { + if ((ci = (ClassInfo)classnames.get(c)) == null) + classnames.put(c, ci = new ClassInfo(false)); + return ci.name; + } + + private String name(ClassDoc c) { + ClassInfo ci; + boolean toPrint; + + if ((ci = (ClassInfo)classnames.get(c.toString())) != null) + toPrint = !ci.nodePrinted; + else { + toPrint = true; + classnames.put(c, ci = new ClassInfo(true)); + } + if (toPrint) { // Associate classnames alias - name = "c" + (new Integer(classnum)).toString(); - classnames.put(c, name); - classnum++; String r = c.toString(); if (!opt.showQualified) { // Create readable string by stripping leading path @@ -134,7 +159,7 @@ class ClassGraph { r = r.substring(dotpos + 1, r.length()); } // Create label - opt.w.print("\t" + name + " ["); + opt.w.print("\t" + ci.name + " ["); if (opt.showAttributes || opt.showOperations) opt.w.print("label=\"{" + r + "\\n|"); else @@ -151,23 +176,75 @@ class ClassGraph { opt.w.print(", fontname=\"Helvetica-Oblique\""); opt.w.println("];"); } - return name; + return ci.name; + } + + private String[] tokenize(String s) { + String r[] = new String[4]; + String remain = s, tok; + int n = 0, pos; + + remain.trim(); + while (remain.length() > 0 && n < 4) { + if (remain.startsWith("\"")) { + // Field in quotes + pos = remain.indexOf('"', 1); + if (pos == -1) + break; + r[n] = remain.substring(1, pos); + if (pos + 1 < remain.length()) + pos++; + } else { + // Space-separated field + pos = remain.indexOf(' ', 0); + if (pos == -1) + r[n] = remain; + else + r[n] = remain.substring(0, pos); + } + remain = remain.substring(pos + 1); + remain.trim(); + // - is used as a placeholder for empy fields + if (r[n].equals("-")) + r[n] = ""; + n++; + } + if (n != 4) + System.err.println("Expected four fields: " + s); + return (r); + } + + private void relation(String tagname, Doc from, String name, String edgetype) { + Tag tags[] = from.tags(tagname); + for (int i = 0; i < tags.length; i++) { + String t[] = tokenize(tags[i].text()); // l-src label l-dst target + opt.w.println("\t" + name + " -> " + name(t[3]) + "[" + + "taillabel=\"" + t[0] + "\", " + + "label=\"" + t[1] + "\", " + + "headlabel=\"" + t[2] + "\", " + + edgetype + "]" + ); + } } public void print() { String cs = name(c); - // Print the derivation path + // Print generalization (through the Java superclass) ClassDoc s = c.superclass(); if (s != null && !s.toString().equals("java.lang.Object")) { opt.w.print("\t" + name(s) + " -> " + cs + " [dir=back,arrowtail=empty];"); opt.w.println("\t//" + c + " extends " + s); } - // Print interfaces + // Print realizations (Java interfaces) ClassDoc ifs[] = c.interfaces(); for (int i = 0; i < ifs.length; i++) { opt.w.print("\t" + name(ifs[i]) + " -> " + cs + " [dir=back,arrowtail=empty,style=dashed];"); opt.w.println("\t//" + c + " implements " + s); } + // Print associations + relation("assoc", c, cs, "arrowhead=none"); + relation("has", c, cs, "arrowhead=none, arrowtail=ediamond"); + relation("composed", c, cs, "arrowhead=none, arrowtail=diamond"); } } @@ -223,6 +300,8 @@ public class UmlGraph { "# Generated by $Id$\n" + "#\n\n" + "digraph G {\n" + + "edge [fontname=\"Helvetica\",fontsize=8,labelfontname=\"Helvetica\",labelfontsize=8];\n" + + "\tnode [fontname=\"Helvetica\",fontsize=8,shape=record];" ); } diff --git a/src/org/umlgraph/doclet/StringUtil.java b/src/org/umlgraph/doclet/StringUtil.java index 4fe564e..49466bc 100644 --- a/src/org/umlgraph/doclet/StringUtil.java +++ b/src/org/umlgraph/doclet/StringUtil.java @@ -52,10 +52,23 @@ class Options { } } +class ClassInfo { + private static int classnum; + /** Alias name for the class */ + String name; + /** True if the class class node has been printed */ + boolean nodePrinted; + + ClassInfo(boolean p) { + nodePrinted = p; + name = "c" + (new Integer(classnum)).toString(); + classnum++; + } +} + class ClassGraph { private ClassDoc c; private static HashMap classnames = new HashMap(); - private static int classnum; private Options opt; ClassGraph(Options iopt, ClassDoc ic) { @@ -118,14 +131,26 @@ class ClassGraph { } } - private String name(ClassDoc c) { - String name; + private String name(String c) { + ClassInfo ci; - if ((name = (String)classnames.get(c)) == null) { + if ((ci = (ClassInfo)classnames.get(c)) == null) + classnames.put(c, ci = new ClassInfo(false)); + return ci.name; + } + + private String name(ClassDoc c) { + ClassInfo ci; + boolean toPrint; + + if ((ci = (ClassInfo)classnames.get(c.toString())) != null) + toPrint = !ci.nodePrinted; + else { + toPrint = true; + classnames.put(c, ci = new ClassInfo(true)); + } + if (toPrint) { // Associate classnames alias - name = "c" + (new Integer(classnum)).toString(); - classnames.put(c, name); - classnum++; String r = c.toString(); if (!opt.showQualified) { // Create readable string by stripping leading path @@ -134,7 +159,7 @@ class ClassGraph { r = r.substring(dotpos + 1, r.length()); } // Create label - opt.w.print("\t" + name + " ["); + opt.w.print("\t" + ci.name + " ["); if (opt.showAttributes || opt.showOperations) opt.w.print("label=\"{" + r + "\\n|"); else @@ -151,23 +176,75 @@ class ClassGraph { opt.w.print(", fontname=\"Helvetica-Oblique\""); opt.w.println("];"); } - return name; + return ci.name; + } + + private String[] tokenize(String s) { + String r[] = new String[4]; + String remain = s, tok; + int n = 0, pos; + + remain.trim(); + while (remain.length() > 0 && n < 4) { + if (remain.startsWith("\"")) { + // Field in quotes + pos = remain.indexOf('"', 1); + if (pos == -1) + break; + r[n] = remain.substring(1, pos); + if (pos + 1 < remain.length()) + pos++; + } else { + // Space-separated field + pos = remain.indexOf(' ', 0); + if (pos == -1) + r[n] = remain; + else + r[n] = remain.substring(0, pos); + } + remain = remain.substring(pos + 1); + remain.trim(); + // - is used as a placeholder for empy fields + if (r[n].equals("-")) + r[n] = ""; + n++; + } + if (n != 4) + System.err.println("Expected four fields: " + s); + return (r); + } + + private void relation(String tagname, Doc from, String name, String edgetype) { + Tag tags[] = from.tags(tagname); + for (int i = 0; i < tags.length; i++) { + String t[] = tokenize(tags[i].text()); // l-src label l-dst target + opt.w.println("\t" + name + " -> " + name(t[3]) + "[" + + "taillabel=\"" + t[0] + "\", " + + "label=\"" + t[1] + "\", " + + "headlabel=\"" + t[2] + "\", " + + edgetype + "]" + ); + } } public void print() { String cs = name(c); - // Print the derivation path + // Print generalization (through the Java superclass) ClassDoc s = c.superclass(); if (s != null && !s.toString().equals("java.lang.Object")) { opt.w.print("\t" + name(s) + " -> " + cs + " [dir=back,arrowtail=empty];"); opt.w.println("\t//" + c + " extends " + s); } - // Print interfaces + // Print realizations (Java interfaces) ClassDoc ifs[] = c.interfaces(); for (int i = 0; i < ifs.length; i++) { opt.w.print("\t" + name(ifs[i]) + " -> " + cs + " [dir=back,arrowtail=empty,style=dashed];"); opt.w.println("\t//" + c + " implements " + s); } + // Print associations + relation("assoc", c, cs, "arrowhead=none"); + relation("has", c, cs, "arrowhead=none, arrowtail=ediamond"); + relation("composed", c, cs, "arrowhead=none, arrowtail=diamond"); } } @@ -223,6 +300,8 @@ public class UmlGraph { "# Generated by $Id$\n" + "#\n\n" + "digraph G {\n" + + "edge [fontname=\"Helvetica\",fontsize=8,labelfontname=\"Helvetica\",labelfontsize=8];\n" + + "\tnode [fontname=\"Helvetica\",fontsize=8,shape=record];" ); } diff --git a/src/org/umlgraph/doclet/UmlGraph.java b/src/org/umlgraph/doclet/UmlGraph.java index 4fe564e..49466bc 100644 --- a/src/org/umlgraph/doclet/UmlGraph.java +++ b/src/org/umlgraph/doclet/UmlGraph.java @@ -52,10 +52,23 @@ class Options { } } +class ClassInfo { + private static int classnum; + /** Alias name for the class */ + String name; + /** True if the class class node has been printed */ + boolean nodePrinted; + + ClassInfo(boolean p) { + nodePrinted = p; + name = "c" + (new Integer(classnum)).toString(); + classnum++; + } +} + class ClassGraph { private ClassDoc c; private static HashMap classnames = new HashMap(); - private static int classnum; private Options opt; ClassGraph(Options iopt, ClassDoc ic) { @@ -118,14 +131,26 @@ class ClassGraph { } } - private String name(ClassDoc c) { - String name; + private String name(String c) { + ClassInfo ci; - if ((name = (String)classnames.get(c)) == null) { + if ((ci = (ClassInfo)classnames.get(c)) == null) + classnames.put(c, ci = new ClassInfo(false)); + return ci.name; + } + + private String name(ClassDoc c) { + ClassInfo ci; + boolean toPrint; + + if ((ci = (ClassInfo)classnames.get(c.toString())) != null) + toPrint = !ci.nodePrinted; + else { + toPrint = true; + classnames.put(c, ci = new ClassInfo(true)); + } + if (toPrint) { // Associate classnames alias - name = "c" + (new Integer(classnum)).toString(); - classnames.put(c, name); - classnum++; String r = c.toString(); if (!opt.showQualified) { // Create readable string by stripping leading path @@ -134,7 +159,7 @@ class ClassGraph { r = r.substring(dotpos + 1, r.length()); } // Create label - opt.w.print("\t" + name + " ["); + opt.w.print("\t" + ci.name + " ["); if (opt.showAttributes || opt.showOperations) opt.w.print("label=\"{" + r + "\\n|"); else @@ -151,23 +176,75 @@ class ClassGraph { opt.w.print(", fontname=\"Helvetica-Oblique\""); opt.w.println("];"); } - return name; + return ci.name; + } + + private String[] tokenize(String s) { + String r[] = new String[4]; + String remain = s, tok; + int n = 0, pos; + + remain.trim(); + while (remain.length() > 0 && n < 4) { + if (remain.startsWith("\"")) { + // Field in quotes + pos = remain.indexOf('"', 1); + if (pos == -1) + break; + r[n] = remain.substring(1, pos); + if (pos + 1 < remain.length()) + pos++; + } else { + // Space-separated field + pos = remain.indexOf(' ', 0); + if (pos == -1) + r[n] = remain; + else + r[n] = remain.substring(0, pos); + } + remain = remain.substring(pos + 1); + remain.trim(); + // - is used as a placeholder for empy fields + if (r[n].equals("-")) + r[n] = ""; + n++; + } + if (n != 4) + System.err.println("Expected four fields: " + s); + return (r); + } + + private void relation(String tagname, Doc from, String name, String edgetype) { + Tag tags[] = from.tags(tagname); + for (int i = 0; i < tags.length; i++) { + String t[] = tokenize(tags[i].text()); // l-src label l-dst target + opt.w.println("\t" + name + " -> " + name(t[3]) + "[" + + "taillabel=\"" + t[0] + "\", " + + "label=\"" + t[1] + "\", " + + "headlabel=\"" + t[2] + "\", " + + edgetype + "]" + ); + } } public void print() { String cs = name(c); - // Print the derivation path + // Print generalization (through the Java superclass) ClassDoc s = c.superclass(); if (s != null && !s.toString().equals("java.lang.Object")) { opt.w.print("\t" + name(s) + " -> " + cs + " [dir=back,arrowtail=empty];"); opt.w.println("\t//" + c + " extends " + s); } - // Print interfaces + // Print realizations (Java interfaces) ClassDoc ifs[] = c.interfaces(); for (int i = 0; i < ifs.length; i++) { opt.w.print("\t" + name(ifs[i]) + " -> " + cs + " [dir=back,arrowtail=empty,style=dashed];"); opt.w.println("\t//" + c + " implements " + s); } + // Print associations + relation("assoc", c, cs, "arrowhead=none"); + relation("has", c, cs, "arrowhead=none, arrowtail=ediamond"); + relation("composed", c, cs, "arrowhead=none, arrowtail=diamond"); } } @@ -223,6 +300,8 @@ public class UmlGraph { "# Generated by $Id$\n" + "#\n\n" + "digraph G {\n" + + "edge [fontname=\"Helvetica\",fontsize=8,labelfontname=\"Helvetica\",labelfontsize=8];\n" + + "\tnode [fontname=\"Helvetica\",fontsize=8,shape=record];" ); }