diff --git a/src/main/java/org/umlgraph/doclet/ClassGraph.java b/src/main/java/org/umlgraph/doclet/ClassGraph.java index a36cf3c..f1b4314 100644 --- a/src/main/java/org/umlgraph/doclet/ClassGraph.java +++ b/src/main/java/org/umlgraph/doclet/ClassGraph.java @@ -19,11 +19,18 @@ package org.umlgraph.doclet; +import static org.umlgraph.doclet.StringUtil.escape; +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.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 +40,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; @@ -159,89 +165,6 @@ class ClassGraph { return buf.toString(); } - /** - * 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()) { - 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 - */ - private 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. - */ - private 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. - */ - private String guilWrap(Options opt, String str) { - return opt.guilOpen + str + opt.guilClose; - } - /** * Print the visibility adornment of element e prefixed by * any stereotypes @@ -397,7 +320,7 @@ 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; @@ -412,7 +335,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; @@ -628,7 +551,7 @@ class ClassGraph { private void allRelation(Options opt, RelationType rt, ClassDoc from) { 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 if (t.length != 4) { System.err.println("Error in " + from + "\n" + tagname + " expects four fields (l-src label l-dst target): " + tag.text()); return; @@ -1013,24 +936,6 @@ 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; - 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(); - } - /** Convert the class name into a corresponding URL */ public String classToUrl(ClassDoc cd, boolean rootClass) { // building relative path for context and package diagrams diff --git a/src/main/java/org/umlgraph/doclet/StringUtil.java b/src/main/java/org/umlgraph/doclet/StringUtil.java index 2aa9eac..c28fc3c 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,104 @@ 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(); + } }