# Changes for page PlantUML Macro

Last modified by Helge Dahl on 2018/03/11 07:52

#### Export

#### Office Formats

Export as PDF Export as ODT Export as RTF

#### Other Formats

Export as HTML
From empty
To version 1.1
edited by Helge Dahl
on 2018/01/23 13:01
Change comment: Imported from XAR

## Summary

- Page properties (6 modified, 0 added, 0 removed)
- Objects (0 modified, 3 added, 0 removed)
  - XWiki.PlantUMLConfigurationClass[0]
  - XWiki.WikiMacroClass[0]
  - XWiki.WikiMacroParameterClass[0]

## Details

Page properties
  Title

    ... | ... | @@ -1,0 +1,1 @@
    | 1 | +PlantUML Macro

  Parent

    ... | ... | @@ -1,0 +1,1 @@
    | 1 | +Main.WebHome

  Author

    ... | ... | @@ -1,1 +1,1 @@
    1 |  | -XWiki.XWikiGuest
    | 1 | +xwiki:XWiki.hde

  Default language

    ... | ... | @@ -1,0 +1,1 @@
    | 1 | +en

  Syntax

    ... | ... | @@ -1,1 +1,1 @@
    1 |  | -XWiki 2.1
    | 1 | +XWiki 2.0

  Content

    ... | ... | @@ -1,0 +1,21 @@
    | 1 | +This macro enables you to include UML diagrams inside your wiki pages using **PlantUML** ([[http://plantuml.sourceforge.net]]).
    | 2 | +
    | 3 | +== Configuration ==
    | 4 | +
    | 5 | +{{velocity}}
    | 6 | +#if ($doc.getObject("XWiki.PlantUMLConfigurationClass").Server != '')
    | 7 | +The configured active server is :** $doc.getObject("XWiki.PlantUMLConfigurationClass").Server **
    | 8 | +#else
    | 9 | +**No server specified**, using the embedded PlantUML implementation.
    | 10 | +#end
    | 11 | +
    | 12 | +To specify your own PlantUML server, {{html}}<a href="$xwiki.getURL( $doc.getFullName(), "edit", "editor=object&classname=XWiki.PlantUMLConfigurationClass&object=0")">edit this URL</a>{{/html}}.
    | 13 | +The default value is {{html}}http://www.plantuml.com/plantuml/{{/html}}
    | 14 | +Be careful, the server URL must end with a slash.
    | 15 | +{{/velocity}}
    | 16 | +
    | 17 | +== Version information ==
    | 18 | +
    | 19 | +{{plantuml}}
    | 20 | +version
    | 21 | +{{/plantuml}}

XWiki.PlantUMLConfigurationClass[0]
XWiki.WikiMacroClass[0]
  Macro code

    ... | ... | @@ -1,0 +1,120 @@
    | 1 | +{{groovy}}
    | 2 | +// Utility class and method from plantUML to encode the UML text. See below the starting point of the macro.
    | 3 | +import java.util.zip.*
    | 4 | +
    | 5 | +byte[] compress(byte[] input) {
    | 6 | + int len = input.length + 100;
    | 7 | + Deflater compresser = new Deflater(9, true);
    | 8 | + compresser.setInput(input);
    | 9 | + compresser.finish();
    | 10 | + byte[] output = new byte[len];
    | 11 | + int compressedDataLength = compresser.deflate(output);
    | 12 | + byte[] result = new byte[compressedDataLength];
    | 13 | + System.arraycopy(output,0,result,0,compressedDataLength);
    | 14 | + return result;
    | 15 | +}
    | 16 | +
    | 17 | +class AsciiEncoder {
    | 18 | + char[] encode6bits = new char[64];
    | 19 | +
    | 20 | + public AsciiEncoder() {
    | 21 | + for (byte b = 0; b < 64; b++) {
    | 22 | + encode6bits[b] = encode6bit(b as byte);
    | 23 | + }
    | 24 | + }
    | 25 | +
    | 26 | + public String encode(byte[] data) {
    | 27 | + final StringBuilder resu = new StringBuilder((int)((data.length * 4 + 2) / 3));
    | 28 | + for (int i = 0; i < data.length; i += 3) {
    | 29 | + append3bytes(resu, data[i] & 0xFF, i + 1 < data.length ? data[i + 1] & 0xFF : 0,
    | 30 | + i + 2 < data.length ? data[i + 2] & 0xFF : 0);
    | 31 | + }
    | 32 | + return resu.toString();
    | 33 | + }
    | 34 | +
    | 35 | + private char encode6bit(byte b) {
    | 36 | + assert b >= 0 && b < 64;
    | 37 | + if (b < 10) {
    | 38 | + return (char)(('0' as char) + b);
    | 39 | + }
    | 40 | + b -= 10;
    | 41 | + if (b < 26) {
    | 42 | + return (char)(('A' as char) + b);
    | 43 | + }
    | 44 | + b -= 26;
    | 45 | + if (b < 26) {
    | 46 | + return (char)(('a' as char) + b);
    | 47 | + }
    | 48 | + b -= 26;
    | 49 | + if (b == 0) {
    | 50 | + return '-' as char;
    | 51 | + }
    | 52 | + if (b == 1) {
    | 53 | + return '_' as char;
    | 54 | + }
    | 55 | + assert false;
    | 56 | + return '?';
    | 57 | + }
    | 58 | +
    | 59 | + private void append3bytes(StringBuilder sb, int b1, int b2, int b3) {
    | 60 | + final int c1 = b1 >> 2;
    | 61 | + final int c2 = ((b1 & 0x3) << 4) | (b2 >> 4);
    | 62 | + final int c3 = ((b2 & 0xF) << 2) | (b3 >> 6);
    | 63 | + final int c4 = b3 & 0x3F;
    | 64 | + sb.append(encode6bits[c1 & 0x3F]);
    | 65 | + sb.append(encode6bits[c2 & 0x3F]);
    | 66 | + sb.append(encode6bits[c3 & 0x3F]);
    | 67 | + sb.append(encode6bits[c4 & 0x3F]);
    | 68 | + }
    | 69 | +}
    | 70 | +
    | 71 | +// Utility method to insert content in the uml script taking care of the @start marker.
    | 72 | +String insertHeader( String header, String origin) {
    | 73 | + def m = origin =~ /(?s)(@start[a-z]++)(.*)/
    | 74 | + if (m.matches()) {
    | 75 | + return m[0][1] + "\n" + header + "\n" + m[0][2]
    | 76 | + } else {
    | 77 | + return header + "\n" + origin
    | 78 | + }
    | 79 | +}
    | 80 | +
    | 81 | +// STARTING POINT
    | 82 | +// Get the uml script
    | 83 | +def umltext = xcontext.macro.content
    | 84 | +
    | 85 | +// Add the optional 'include' content
    | 86 | +def include = xcontext.macro.params.include
    | 87 | +if (include) {
    | 88 | + def incDoc = xwiki.getDocument(include)
    | 89 | + if (!incDoc.isNew()) {
    | 90 | + umltext = insertHeader(incDoc.content, umltext)
    | 91 | + } else {
    | 92 | + println "**PlantUMLMacro WARNING**: Can't include page "+include
    | 93 | + }
    | 94 | +}
    | 95 | +
    | 96 | +// Get the configured server
    | 97 | +def macrodoc = xcontext.getMacro().get("doc")
    | 98 | +def serverurl
    | 99 | +def imageFormat
    | 100 | +def enableImageMap
    | 101 | +if (macrodoc.getObject("XWiki.PlantUMLConfigurationClass") != null) {
    | 102 | + serverurl = macrodoc.getObject('XWiki.PlantUMLConfigurationClass').getProperty('Server').value
    | 103 | + imageFormat = macrodoc.getObject('XWiki.PlantUMLConfigurationClass').getProperty('ImageFormat').value
    | 104 | + enableImageMap = macrodoc.getObject('XWiki.PlantUMLConfigurationClass').getProperty('EnableImageMap').value
    | 105 | +}
    | 106 | +
    | 107 | +
    | 108 | +if (serverurl == "") { // Uses the internal PlantUMLMacroGClass groovy implementation
    | 109 | + gObj = xwiki.parseGroovyFromPage( "XWiki.PlantUMLMacroGClass", "XWiki.PlantUMLMacroGClass")
    | 110 | + gObj.setObjects(doc, xcontext, umltext, imageFormat, enableImageMap)
    | 111 | + println gObj.run( request, response)
    | 112 | +} else { // Uses the external configured PlantUML server
    | 113 | + // Encode the UML content
    | 114 | + byte[] data = umltext.getBytes("UTF-8")
    | 115 | + byte[] compressed = compress(data)
    | 116 | + String encoded = new AsciiEncoder().encode(compressed)
    | 117 | + // Output the image wiki tag
    | 118 | + println "[[image:"+serverurl+"img/"+encoded+"||style=\"max-width:100%\"]]"
    | 119 | +}
    | 120 | +{{/groovy}}

  Content description (Not applicable for "No content" type)

    ... | ... | @@ -1,0 +1,1 @@
    | 1 | +The diagram definition using PlanUML's syntax.

  Macro content type

    ... | ... | @@ -1,0 +1,1 @@
    | 1 | +Mandatory

  Default category

    ... | ... | @@ -1,0 +1,1 @@
    | 1 | +content

  Macro description

    ... | ... | @@ -1,0 +1,1 @@
    | 1 | +Generate Diagrams using PlantUML.

  Macro id

    ... | ... | @@ -1,0 +1,1 @@
    | 1 | +plantuml

  Macro name

    ... | ... | @@ -1,0 +1,1 @@
    | 1 | +PlantUML

  Supports inline mode

    ... | ... | @@ -1,0 +1,1 @@
    | 1 | +No

  Macro visibility

    ... | ... | @@ -1,0 +1,1 @@
    | 1 | +Global

XWiki.WikiMacroParameterClass[0]
  Parameter description

    ... | ... | @@ -1,0 +1,1 @@
    | 1 | +The content of the specified wiki page will be inserted at the begining of the diagram definition. Please note the page name may be prefixed with its space and is case sensitive. For example, you may include: Sandbox.UMLskin

  Parameter mandatory

    ... | ... | @@ -1,0 +1,1 @@
    | 1 | +No

  Parameter name

    ... | ... | @@ -1,0 +1,1 @@
    | 1 | +include

# Applications

# Tips

Jump to any page in the wiki with Ctrl+G or Meta+G.
See more shortcuts.

# Need help?

If you need help with XWiki you can contact:

- Community Support
- Professional Support