Index: xwiki-platform-core/xwiki-core/src/main/java/com/xpn/xwiki/plugin/graphviz/GraphVizMacro.java =================================================================== --- xwiki-platform-core/xwiki-core/src/main/java/com/xpn/xwiki/plugin/graphviz/GraphVizMacro.java (revision 11289) +++ xwiki-platform-core/xwiki-core/src/main/java/com/xpn/xwiki/plugin/graphviz/GraphVizMacro.java (working copy) @@ -23,6 +23,9 @@ import java.io.IOException; import java.io.Writer; +import java.util.Arrays; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.radeox.api.engine.RenderEngine; import org.radeox.api.engine.context.RenderContext; @@ -33,49 +36,175 @@ import com.xpn.xwiki.XWikiContext; import com.xpn.xwiki.render.XWikiRadeoxRenderEngine; -public class GraphVizMacro extends BaseLocaleMacro -{ - public String getLocaleKey() - { - return "macro.graphviz"; - } +/** + *

+ * Macro used to invoke GraphViz and render its output on a XWiki page. + *

+ *

+ * For it to work properly, you must have the GraphViz plugin enabled and + * configured. + *

+ *

+ * The content of the macro is the source code for the graph, using GraphViz DOT language. + *

+ * The parameters are as follows: + *

    + *
  1. type: [dot] or neato. Specifies which engine will be used to + * produce the graph.
  2. + *
  3. text: Text attribute for the image (floating text box when you + * hover it). Do not specify it if you want to use GraphViz tooltip + * attribute. With the tooltip attributes you can generate different text + * values for different regions of the image.
  4. + *
  5. height: Image height in pixels.
  6. + *
  7. width: Image width in pixels.
  8. + *
  9. alt: Alternative text (alt attribute) for the image, in case it + * cannot be rendered by the browser.
  10. + *
  11. format: This attribute specifies what will be GraphViz output + * and also how it will be rendered in the HTML.
    The HTML output of the + * macro will be one of the following, depending on this attribute: + * + *
  12. + *
  13. clickable: If present and not false indicates that the IMG tag + * must reference the link map produced by GraphViz ("cmapx" format). This + * parameter will have no effect if format specifies anything different + * from an IMG tag to be rendered - what doesn't mean you can't have clickable + * SVG images, you just don't need an extra map tag for that.
  14. + *
+ *

+ */ +public class GraphVizMacro extends BaseLocaleMacro { + public String getLocaleKey() { + return "macro.graphviz"; + } - @Override - public void execute(Writer writer, MacroParameter params) throws IllegalArgumentException, IOException - { + @Override + public void execute(Writer writer, MacroParameter params) + throws IllegalArgumentException, IOException { - RenderContext context = params.getContext(); - RenderEngine engine = context.getRenderEngine(); + RenderContext context = params.getContext(); + RenderEngine engine = context.getRenderEngine(); - XWikiContext xcontext = ((XWikiRadeoxRenderEngine) engine).getXWikiContext(); - XWiki xwiki = xcontext.getWiki(); + XWikiContext xcontext = ((XWikiRadeoxRenderEngine) engine) + .getXWikiContext(); + XWiki xwiki = xcontext.getWiki(); - GraphVizPlugin plugin = (GraphVizPlugin) xwiki.getPlugin("graphviz", xcontext); - // If the plugin is not loaded - if (plugin == null) { - writer.write("Plugin not loaded"); - return; - } + GraphVizPlugin plugin = (GraphVizPlugin) xwiki.getPlugin("graphviz", + xcontext); + // If the plugin is not loaded + if (plugin == null) { + writer.write("Plugin not loaded"); + return; + } - boolean dot = !("neato").equals(params.get("type")); - StringBuffer str = new StringBuffer(); - String img = params.get("text", 0); - String height = params.get("height", 1); - String width = params.get("width", 2); + boolean dot = !("neato").equals(params.get("type")); + String text = nullifyBadParameter(params.get("text", 0)); + String height = nullifyBadParameter(params.get("height", 1)); + String width = nullifyBadParameter(params.get("width", 2)); + String alt = nullifyBadParameter(params.get("alt", 3)); + String format = nullifyBadParameter(params.get("format", 4)); + if (format == null) + format = "png"; + String clickableStr = nullifyBadParameter(params.get("clickable", 5)); + boolean clickable = clickableStr != null + && !"false".equals(clickableStr); + String dottext = params.getContent(); - String dottext = params.getContent(); - str.append(""); - writer.write(str.toString()); - } + /* please KEEP THE ARRAYS SORTED */ + final String[] embedTagFormats = new String[] { "svg", "svgz" }; + final String[] plainTextFormats = new String[] { "canon", "cmapx", + "cmapx_np", "dot", "imap", "imap_np", "plain", "plain-ext", + "xdot" }; + + if (Arrays.binarySearch(plainTextFormats, format) >= 0) { + /* producing plain text output */ + byte[] graphvizOutput = plugin.getDotImage(dottext, format, dot); + writer.write(new String(graphvizOutput)); + } else if (Arrays.binarySearch(embedTagFormats, format) >= 0) { + /* producing embed tag output */ + writer.write(""); + } else { + /* producing img tag output */ + if (clickable) { + /* creates the map */ + byte[] graphvizOutput = plugin.getDotImage(dottext, "cmapx", + dot); + writer.write(new String(graphvizOutput)); + } + writer.write(""); + } + } + + private void writeImgOrEmbedCommonContent(Writer writer, + GraphVizPlugin plugin, String dottext, String text, String height, + String width, String alt, String format, boolean dot, + XWikiContext context) throws IOException { + + writer.write("src=\""); + writer.write(plugin.getDotResultURL(dottext, dot, format, context)); + writer.write("\" "); + if ((!"none".equals(height)) && (height != null)) { + writer.write("height=\""); + writer.write(height); + writer.write("\" "); + } + if ((!"none".equals(width)) && (width != null)) { + writer.write("width=\""); + writer.write(width); + writer.write("\" "); + } + if (text != null) { + writer.write("text=\""); + writer.write(text); + writer.write("\" "); + } + if (alt != null) { + writer.write("alt=\""); + writer.write(alt); + writer.write('"'); + } + } + + /** + * Checks if a parameter came with a '=' sign and return null in the case. + * Else, returns the parameter itself. + * + * @param radeoxParam + * @return String + */ + private String nullifyBadParameter(String radeoxParam) { + return radeoxParam != null && radeoxParam.indexOf('=') >= 0 ? null + : radeoxParam; + } } Index: xwiki-platform-core/xwiki-core/src/main/java/com/xpn/xwiki/plugin/graphviz/GraphVizPlugin.java =================================================================== --- xwiki-platform-core/xwiki-core/src/main/java/com/xpn/xwiki/plugin/graphviz/GraphVizPlugin.java (revision 11289) +++ xwiki-platform-core/xwiki-core/src/main/java/com/xpn/xwiki/plugin/graphviz/GraphVizPlugin.java (working copy) @@ -180,9 +180,13 @@ } } FileInputStream fis = new FileInputStream(ofile); - byte[] result = new byte[(int) ofile.length()]; - fis.read(result); - return result; + try { + byte[] result = new byte[(int) ofile.length()]; + fis.read(result); + return result; + } finally { + fis.close(); + } } public byte[] readDotImage(File ofile) throws FileNotFoundException, IOException @@ -250,7 +254,30 @@ public String getDotImageURL(String content, boolean dot, XWikiContext context) throws IOException { - String filename = writeDotImage(content, "png", dot); + return getDotResultURL(content, dot, "png", context); + } + + /** + *

+ * Executes graphviz and returns the url for the produced file. + *

+ * + * @param content + * GraphViz source code. View + * http://www.graphviz.org/doc/info/lang.html for the language + * specification. + * @param dot + * Whether the dot engine should be used instead of the neato + * engine. Other engines are not supported. + * @param format + * Any GraphViz output format. View + * http://www.graphviz.org/doc/info/output.html for more + * information. + * @param context + * XWikiContext + */ + public String getDotResultURL(String content, boolean dot, String format, XWikiContext context) throws IOException { + String filename = writeDotImage(content, format, dot); return context.getDoc().getAttachmentURL(filename, "dot", context); } }