You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2021/02/08 11:48:50 UTC

[isis] branch master updated: ISIS-2502: tooling: some core improvements

This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git


The following commit(s) were added to refs/heads/master by this push:
     new d242855  ISIS-2502: tooling: some core improvements
d242855 is described below

commit d242855c1da667cfb2754b0fde714738465a5a9e
Author: Andi Huber <ah...@apache.org>
AuthorDate: Mon Feb 8 12:48:33 2021 +0100

    ISIS-2502: tooling: some core improvements
    
    properly pass source and diagram generators through (tested) asciidoc
    factories
---
 .../RestServiceSimpifiedRepresentationTest.java    |  10 +-
 .../isis/tooling/cli/projdoc/ProjectDocModel.java  |   6 +-
 .../format/UnitFormatterWithSourceAndCallouts.java |   3 +-
 .../format/UnitFormatterWithSourceAndSections.java |   3 +-
 .../isis/tooling/model4adoc/AsciiDocFactory.java   | 156 +++++++++++++++++----
 .../apache/isis/tooling/model4adoc/NodeWriter.java |  72 +++++++++-
 .../isis/tooling/model4adoc/ast/SimpleBlock.java   |  13 ++
 .../ast/{SourceTest.java => PlantumlTest.java}     |  38 +++--
 .../tooling/model4adoc/test/ast/SourceTest.java    |  20 ++-
 .../tooling/model4adoc/test/ast/plantuml-svg.adoc  |   7 +
 10 files changed, 276 insertions(+), 52 deletions(-)

diff --git a/regressiontests/incubating/src/test/java/org/apache/isis/testdomain/rest/RestServiceSimpifiedRepresentationTest.java b/regressiontests/incubating/src/test/java/org/apache/isis/testdomain/rest/RestServiceSimpifiedRepresentationTest.java
index 490ec7e..e034dff 100644
--- a/regressiontests/incubating/src/test/java/org/apache/isis/testdomain/rest/RestServiceSimpifiedRepresentationTest.java
+++ b/regressiontests/incubating/src/test/java/org/apache/isis/testdomain/rest/RestServiceSimpifiedRepresentationTest.java
@@ -508,7 +508,8 @@ class RestServiceSimpifiedRepresentationTest {
         void next(String javaSource) {
             
             row = row(table);
-            cell(table, row, AsciiDocFactory.SourceFactory.java(javaSource, null));
+            cell(table, row, AsciiDocFactory.toString(doc->
+                AsciiDocFactory.SourceFactory.java(doc, javaSource, null)));
             requestAndResponseCellContent = new StringBuilder();
         }
         
@@ -517,7 +518,9 @@ class RestServiceSimpifiedRepresentationTest {
                 Map<String, List<String>> headers, String body) {
             
             requestAndResponseCellContent.append("==== REQUEST\n\n");
-            requestAndResponseCellContent.append(AsciiDocFactory.SourceFactory.json(body, null));
+            requestAndResponseCellContent.append(
+                    AsciiDocFactory.toString(doc->
+                        AsciiDocFactory.SourceFactory.json(doc, body, null)));
         }
 
         @Override
@@ -531,7 +534,8 @@ class RestServiceSimpifiedRepresentationTest {
             .append("\n==== RESPONSE\n\n")
             .append(String.format("- HTTP return code: %d\n", httpReturnCode)) 
             .append(String.format("- Representation Type: %s\n\n", reprType))
-            .append(AsciiDocFactory.SourceFactory.json(body, null));
+            .append(AsciiDocFactory.toString(doc->
+                AsciiDocFactory.SourceFactory.json(doc, body, null)));
             
             cell(table, row, requestAndResponseCellContent.toString());
         }
diff --git a/tooling/cli/src/main/java/org/apache/isis/tooling/cli/projdoc/ProjectDocModel.java b/tooling/cli/src/main/java/org/apache/isis/tooling/cli/projdoc/ProjectDocModel.java
index 4b9eda7..5fef064 100644
--- a/tooling/cli/src/main/java/org/apache/isis/tooling/cli/projdoc/ProjectDocModel.java
+++ b/tooling/cli/src/main/java/org/apache/isis/tooling/cli/projdoc/ProjectDocModel.java
@@ -269,7 +269,8 @@ public class ProjectDocModel {
         public String toAsciiDoc(String softwareSystemName) {
             val key = c4.getWorkspaceName();
 
-            return AsciiDocFactory.SourceFactory.plantuml(toPlantUml(softwareSystemName), key, null);
+            return AsciiDocFactory.toString(doc->
+                        AsciiDocFactory.DiagramFactory.plantumlPng(doc, toPlantUml(softwareSystemName), key, null));
         }
     }
 
@@ -412,7 +413,8 @@ public class ProjectDocModel {
         appendKeyValue(coors, "Folder", projRelativePath);
         return String.format("%s\n%s",
                 module.getName(),
-                AsciiDocFactory.SourceFactory.yaml(coors.toString(), null));
+                AsciiDocFactory.toString(doc->
+                    AsciiDocFactory.SourceFactory.yaml(doc, coors.toString(), null)));
     }
 
     private void appendKeyValue(StringBuilder sb, String key, String value) {
diff --git a/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/format/UnitFormatterWithSourceAndCallouts.java b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/format/UnitFormatterWithSourceAndCallouts.java
index be7528c..1c9e2bf 100644
--- a/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/format/UnitFormatterWithSourceAndCallouts.java
+++ b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/format/UnitFormatterWithSourceAndCallouts.java
@@ -42,7 +42,8 @@ extends UnitFormatterAbstract {
 
         final String javaSource = Snippets.javaSourceFor(unit);
         return Optional.of(
-                AsciiDocFactory.SourceFactory.java(javaSource, unit.getCanonicalName() + ".java"));
+                AsciiDocFactory.toString(doc->
+                    AsciiDocFactory.SourceFactory.java(doc, javaSource, unit.getCanonicalName() + ".java")));
     }
 
     @Override
diff --git a/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/format/UnitFormatterWithSourceAndSections.java b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/format/UnitFormatterWithSourceAndSections.java
index 6acd565..9615c3c 100644
--- a/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/format/UnitFormatterWithSourceAndSections.java
+++ b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/format/UnitFormatterWithSourceAndSections.java
@@ -52,7 +52,8 @@ extends UnitFormatterAbstract {
 
         final String javaSource = Snippets.javaSourceFor(unit);
         return Optional.of(
-                AsciiDocFactory.SourceFactory.java(javaSource, unit.getCanonicalName() + ".java"));
+                AsciiDocFactory.toString(doc->
+                    AsciiDocFactory.SourceFactory.java(doc, javaSource, unit.getCanonicalName() + ".java")));
     }
 
     @Override
diff --git a/tooling/model4adoc/src/main/java/org/apache/isis/tooling/model4adoc/AsciiDocFactory.java b/tooling/model4adoc/src/main/java/org/apache/isis/tooling/model4adoc/AsciiDocFactory.java
index b6523a7..61b2ff3 100644
--- a/tooling/model4adoc/src/main/java/org/apache/isis/tooling/model4adoc/AsciiDocFactory.java
+++ b/tooling/model4adoc/src/main/java/org/apache/isis/tooling/model4adoc/AsciiDocFactory.java
@@ -18,6 +18,9 @@
  */
 package org.apache.isis.tooling.model4adoc;
 
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+
 import javax.annotation.Nullable;
 
 import org.asciidoctor.ast.Block;
@@ -30,6 +33,7 @@ import org.asciidoctor.ast.StructuralNode;
 import org.asciidoctor.ast.Table;
 
 import org.apache.isis.commons.collections.Can;
+import org.apache.isis.commons.internal.base._Refs;
 import org.apache.isis.commons.internal.base._Strings;
 import org.apache.isis.commons.internal.base._Text;
 import org.apache.isis.tooling.model4adoc.ast.SimpleBlock;
@@ -64,6 +68,24 @@ public class AsciiDocFactory {
     public static Document doc() {
         return new SimpleDocument();
     }
+    
+    /**
+     * syntactic sugar
+     */
+    public static Document doc(Consumer<Document> documentBuilder) {
+        val doc = doc();
+        documentBuilder.accept(doc);
+        return doc;
+    }
+    
+    /**
+     * syntactic sugar
+     */
+    public static String toString(Consumer<Document> documentBuilder) {
+        val doc = doc();
+        documentBuilder.accept(doc);
+        return AsciiDocWriter.toString(doc);
+    }
 
     // -- ATTRIBUTES
 
@@ -154,6 +176,29 @@ public class AsciiDocFactory {
         }
         return sourceBlock;
     }
+    
+    public static Block diagramBlock(
+            StructuralNode parent, 
+            @NonNull String diagramType, 
+            @NonNull Can<String> diagramOptions, 
+            @NonNull String source) {
+        
+        val diagramBlock = block(parent, source);
+        
+        _Strings.nonEmpty(diagramType)
+            .ifPresent(diagramBlock::setStyle);
+        
+        val attributes = diagramOptions.add(0, diagramType);
+        val attributeIndex = _Refs.intRef(1);
+        
+        // add options
+        attributes.forEach(opt->{
+            diagramBlock.setAttribute(""+attributeIndex.getValue(), opt, true);
+            attributeIndex.inc();
+        });
+
+        return diagramBlock;
+    }
 
     // -- CALLOUTS
 
@@ -265,28 +310,29 @@ public class AsciiDocFactory {
 
     public static class SourceFactory {
 
-        public static String wrap(@NonNull String sourceType, @NonNull String source, @Nullable String title, Can<String> options) {
-            val sb = new StringBuilder();
-            sb.append("[").append(sourceType);
-            options.stream().map(String::trim).filter(_Strings::isNotEmpty).map(s->","+s).forEach(sb::append);
-            sb.append("]\n");
+        public static Block sourceBlock(
+                @NonNull Document doc,
+                @NonNull String languageAndOptions, 
+                @NonNull String source, 
+                @Nullable String title) {
             
-            if(_Strings.isNotEmpty(title)) {
-                val trimmedTitle = title.trim();
-                if(!trimmedTitle.isEmpty()) {
-                    sb.append(".").append(trimmedTitle).append("\n");
-                }
-            }
+            val sourceBlock = AsciiDocFactory.sourceBlock(doc,
+                    languageAndOptions,
+                    
+                    _Text.normalize(_Text.getLines(source))
+                    .stream()
+                    .collect(Collectors.joining("\n")));
             
-            sb.append("----\n");
-            _Text.normalize(_Text.getLines(source))
-            .forEach(line->sb.append(line).append("\n"));
-            sb.append("----\n");
-            return sb.toString();
-        }
+            _Strings.nonEmpty(title)
+                .ifPresent(sourceBlock::setTitle);
 
-        public static String xml(@NonNull String xmlSource, @Nullable String title) {
-            return wrap("source,xml", xmlSource, title, Can.empty());
+            return sourceBlock;
+        }
+        
+        public static String asAdocSource() {
+            
+            val doc = AsciiDocFactory.doc();
+            return AsciiDocWriter.toString(doc);
         }
 
 //        [source,java]
@@ -296,31 +342,83 @@ public class AsciiDocFactory {
 //            ...
 //        }
 //        ----
-        public static String java(@NonNull String javaSource, @Nullable String title) {
-            return wrap("source,java", javaSource, title, Can.empty());
+        public static Block java(
+                @NonNull Document doc,
+                @NonNull String javaSource, 
+                @Nullable String title) {
+            return sourceBlock(doc, "java", javaSource, title);
         }
 
-        public static String json(@NonNull String jsonSource, @Nullable String title) {
-            return wrap("source,json", jsonSource, title, Can.empty());
+        public static Block json(
+                @NonNull Document doc,
+                @NonNull String jsonSource, 
+                @Nullable String title) {
+            return sourceBlock(doc, "json", jsonSource, title);
         }
 
-        public static String yaml(@NonNull String yamlSource, @Nullable String title) {
-            return wrap("source,yaml", yamlSource, title, Can.empty());
+        public static Block xml(
+                @NonNull Document doc,
+                @NonNull String xmlSource, 
+                @Nullable String title) {
+            return sourceBlock(doc, "xml", xmlSource, title);
+        }
+        
+        public static Block yaml(
+                @NonNull Document doc,
+                @NonNull String yamlSource, 
+                @Nullable String title) {
+            return sourceBlock(doc, "yaml", yamlSource, title);
         }
 
+    }
+    
+    public static class DiagramFactory {
+        
+        public static Block diagramBlock(
+                @NonNull Document doc,
+                @NonNull String diagramType, 
+                @NonNull Can<String> diagramOptions,
+                @NonNull String source, 
+                @Nullable String title) {
+            
+            val sourceBlock = AsciiDocFactory.diagramBlock(doc,
+                    diagramType,
+                    diagramOptions,
+                    _Text.normalize(_Text.getLines(source))
+                    .stream()
+                    .collect(Collectors.joining("\n")));
+            
+            _Strings.nonEmpty(title)
+                .ifPresent(sourceBlock::setTitle);
+
+            return sourceBlock;
+        }
+        
 //      [plantuml,c4-demo,png]
 //      ----
 //      @startuml
 //      ...
 //      @enduml
 //      ----
-        public static String plantuml(@NonNull String plantumlSource, @NonNull String diagramKey, @Nullable String title) {
-            return wrap(String.format("plantuml,%s,png", diagramKey), plantumlSource, title, Can.of());
+        public static Block plantumlPng(
+                @NonNull Document doc,
+                @NonNull String plantumlSource,
+                @NonNull String diagramKey,
+                @Nullable String title) {
+            return diagramBlock(doc, "plantuml", Can.of(diagramKey, "png"), plantumlSource, title);
         }
-
-
+        
+        public static Block plantumlSvg(
+                @NonNull Document doc,
+                @NonNull String plantumlSource,
+                @NonNull String diagramKey,
+                @Nullable String title) {
+            return diagramBlock(doc, "plantuml", Can.of(diagramKey, "svg"), plantumlSource, title);
+        }
+        
     }
 
+
     // -- HELPER
 
     private static Column getOrCreateColumn(Table table, int colIndex) {
diff --git a/tooling/model4adoc/src/main/java/org/apache/isis/tooling/model4adoc/NodeWriter.java b/tooling/model4adoc/src/main/java/org/apache/isis/tooling/model4adoc/NodeWriter.java
index b46e232..f5102d8 100644
--- a/tooling/model4adoc/src/main/java/org/apache/isis/tooling/model4adoc/NodeWriter.java
+++ b/tooling/model4adoc/src/main/java/org/apache/isis/tooling/model4adoc/NodeWriter.java
@@ -24,9 +24,11 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import java.util.Set;
 import java.util.Stack;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
+import java.util.stream.IntStream;
 import java.util.stream.Stream;
 
 import org.asciidoctor.ast.Block;
@@ -41,6 +43,7 @@ import org.apache.isis.commons.internal.base._Strings;
 import org.apache.isis.commons.internal.base._Text;
 import org.apache.isis.commons.internal.collections._Arrays;
 import org.apache.isis.commons.internal.collections._Lists;
+import org.apache.isis.commons.internal.collections._Sets;
 
 import lombok.NonNull;
 import lombok.RequiredArgsConstructor;
@@ -77,6 +80,39 @@ final class NodeWriter implements StructuralNodeVisitor {
 //    @Override
 //    public void documentTail(Document doc, int depth) {
 //    }
+    
+    // -- KNOWN DIAGRAM TYPES
+    
+    private static Set<String> KNOWN_DIAGRAM_TYPES = _Sets.of(
+        "a2s",
+        "actdiag",
+        "blockdiag",
+        "bpmn",
+        "bytefield",
+        "ditaa",
+        "dpic",
+        "erd",
+        "gnuplot",
+        "graphviz",
+        "meme",
+        "mermaid",
+        "msc",
+        "nomnoml",
+        "nwdiag",
+        "packetdiag",
+        "pikchr",
+        "plantuml",
+        "rackdiag",
+        "seqdiag",
+        "shaape",
+        "smcat",
+        "svgbob",
+        "symbolator",
+        "syntrax",
+        "umlet",
+        "vega",
+        "vegalite",
+        "wavedrom");
 
     // -- BLOCK
 
@@ -86,6 +122,8 @@ final class NodeWriter implements StructuralNodeVisitor {
         LISTING_BLOCK("listing"::equals),
         CALLOUT_LIST("arabic"::equals),
         COLLAPSIBLE_BLOCK("example"::equals),
+        SOURCE_BLOCK("source"::equals),
+        DIAGRAM_BLOCK(KNOWN_DIAGRAM_TYPES::contains),
         ADMONITION_NOTE("NOTE"::equals),
         ADMONITION_TIP("TIP"::equals),
         ADMONITION_IMPORTANT("IMPORTANT"::equals),
@@ -113,6 +151,12 @@ final class NodeWriter implements StructuralNodeVisitor {
         public boolean isCollapsibleBlock() {
             return this==Style.COLLAPSIBLE_BLOCK;
         }
+        public boolean isSourceBlock() {
+            return this==Style.SOURCE_BLOCK;
+        }
+        public boolean isDiagramBlock() {
+            return this==Style.DIAGRAM_BLOCK;
+        }
         public boolean isAdmonition() {
             return name().startsWith("ADMONITION_");
         }
@@ -149,8 +193,30 @@ final class NodeWriter implements StructuralNodeVisitor {
         } else if(style.isCollapsibleBlock()) {
             println("[%collapsible]");
             _Strings.nonEmpty(block.getTitle())
-            .ifPresent(this::printBlockTitle);
+                .ifPresent(this::printBlockTitle);
             println("====");
+        } else if(style.isSourceBlock()) {
+            val language = (String)block.getAttribute("language");
+            if(_Strings.isNotEmpty(language)) {
+                printfln("[source,%s]", language);    
+            } else {
+                printfln("[source]");
+            }
+            _Strings.nonEmpty(block.getTitle())
+                .ifPresent(this::printBlockTitle);
+            println("----");
+        } if(style.isDiagramBlock()) {
+            
+            val diagramTypeAndOptions = IntStream
+                    .iterate(1, index->block.getAttribute(""+index)!=null, index->index+1)
+                    .mapToObj(index->(String)block.getAttribute(""+index))
+                    .collect(Collectors.joining(","));
+                
+            printfln("[%s]", diagramTypeAndOptions);    
+            
+            _Strings.nonEmpty(block.getTitle())
+                .ifPresent(this::printBlockTitle);
+            println("----");
         }
 
         for(val line : block.getLines()) {
@@ -173,7 +239,9 @@ final class NodeWriter implements StructuralNodeVisitor {
             if(block.getBlocks().size()>0) {
                 println("====");
             }
-        } else if(style.isListingBlock()) {
+        } else if(style.isListingBlock()
+                || style.isSourceBlock()
+                || style.isDiagramBlock()) {
             println("----");
         } else if(style.isCollapsibleBlock()) {
             println("====");
diff --git a/tooling/model4adoc/src/main/java/org/apache/isis/tooling/model4adoc/ast/SimpleBlock.java b/tooling/model4adoc/src/main/java/org/apache/isis/tooling/model4adoc/ast/SimpleBlock.java
index e47a469..a0660b1 100644
--- a/tooling/model4adoc/src/main/java/org/apache/isis/tooling/model4adoc/ast/SimpleBlock.java
+++ b/tooling/model4adoc/src/main/java/org/apache/isis/tooling/model4adoc/ast/SimpleBlock.java
@@ -64,4 +64,17 @@ public class SimpleBlock extends SimpleStructuralNode implements Block {
         }
         setLines(Arrays.asList(source.replace("\r", "").split("\n")));
     }
+    
+    @Override
+    public void setStyle(String style) {
+        setAttribute("style", style, true);
+        super.setStyle(style);
+    }
+    
+    @Override
+    public void setTitle(String title) {
+        setAttribute("title", title, true);
+        super.setTitle(title);
+    }
+    
 }
diff --git a/tooling/model4adoc/src/test/java/org/apache/isis/tooling/model4adoc/test/ast/SourceTest.java b/tooling/model4adoc/src/test/java/org/apache/isis/tooling/model4adoc/test/ast/PlantumlTest.java
similarity index 63%
copy from tooling/model4adoc/src/test/java/org/apache/isis/tooling/model4adoc/test/ast/SourceTest.java
copy to tooling/model4adoc/src/test/java/org/apache/isis/tooling/model4adoc/test/ast/PlantumlTest.java
index 2642dd6..9bd5a80 100644
--- a/tooling/model4adoc/src/test/java/org/apache/isis/tooling/model4adoc/test/ast/SourceTest.java
+++ b/tooling/model4adoc/src/test/java/org/apache/isis/tooling/model4adoc/test/ast/PlantumlTest.java
@@ -24,40 +24,56 @@ import org.asciidoctor.ast.Document;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.tooling.model4adoc.AsciiDocFactory;
 
 import static org.apache.isis.tooling.model4adoc.AsciiDocFactory.doc;
 
-class SourceTest extends AbstractAsciiDocWriterTest {
+import lombok.val;
+
+class PlantumlTest extends AbstractAsciiDocWriterTest {
 
     private Document doc;
 
     @BeforeEach
     void setUp() throws Exception {
         doc = doc();
-        super.adocSourceResourceLocation = "source.adoc";
+        super.adocSourceResourceLocation = "plantuml-svg.adoc";
         super.debugEnabled = true;
         super.skipAsciidocjComplianceTest = true;
     }
 
-    // = Source
+    // = Plantuml
     //
-    // [source, java]
-    // .Java Example
+    // [plantuml,alice-and-bob,svg]
+    // .Alice and Bob
     // ----
-    // class Hello {
-    // }
+    // Bob->Alice : hello
     // ----
     @Test
-    void testSourceFactory() throws IOException {
+    void testSourceBlock() throws IOException {
+        
+        doc.setTitle("Plantuml");
         
-        doc.setTitle("Source");
+        val diagramBlock = AsciiDocFactory
+                .diagramBlock(doc, "plantuml", Can.of("alice-and-bob" ,"svg"), "Bob->Alice : hello");
         
-        AsciiDocFactory.sourceBlock(doc, "java", AsciiDocFactory.SourceFactory
-                .java("class Hello {\n}", "Java Example"));
+        diagramBlock.setTitle("Alice and Bob");
+        
+        _Debug.debug(doc);
         
         assertDocumentIsCorrectlyWritten(doc);
     }
     
+    @Test
+    void testSourceFactory() throws IOException {
+        
+        doc.setTitle("Plantuml");
+        
+        AsciiDocFactory.DiagramFactory
+                .plantumlSvg(doc, "Bob->Alice : hello", "alice-and-bob", "Alice and Bob");
+        
+        assertDocumentIsCorrectlyWritten(doc);
+    }
 
 }
diff --git a/tooling/model4adoc/src/test/java/org/apache/isis/tooling/model4adoc/test/ast/SourceTest.java b/tooling/model4adoc/src/test/java/org/apache/isis/tooling/model4adoc/test/ast/SourceTest.java
index 2642dd6..9c25e45 100644
--- a/tooling/model4adoc/src/test/java/org/apache/isis/tooling/model4adoc/test/ast/SourceTest.java
+++ b/tooling/model4adoc/src/test/java/org/apache/isis/tooling/model4adoc/test/ast/SourceTest.java
@@ -28,6 +28,8 @@ import org.apache.isis.tooling.model4adoc.AsciiDocFactory;
 
 import static org.apache.isis.tooling.model4adoc.AsciiDocFactory.doc;
 
+import lombok.val;
+
 class SourceTest extends AbstractAsciiDocWriterTest {
 
     private Document doc;
@@ -49,15 +51,27 @@ class SourceTest extends AbstractAsciiDocWriterTest {
     // }
     // ----
     @Test
-    void testSourceFactory() throws IOException {
+    void testSourceBlock() throws IOException {
         
         doc.setTitle("Source");
         
-        AsciiDocFactory.sourceBlock(doc, "java", AsciiDocFactory.SourceFactory
-                .java("class Hello {\n}", "Java Example"));
+        val sourceBlock = AsciiDocFactory.sourceBlock(doc, "java", "class Hello {\n}");
+        
+        sourceBlock.setTitle("Java Example");
         
         assertDocumentIsCorrectlyWritten(doc);
     }
     
+    @Test
+    void testSourceFactory() throws IOException {
+        
+        doc.setTitle("Source");
+        
+        AsciiDocFactory.SourceFactory
+                .java(doc, "class Hello {\n}", "Java Example");
+        
+        assertDocumentIsCorrectlyWritten(doc);
+    }
+   
 
 }
diff --git a/tooling/model4adoc/src/test/resources/org/apache/isis/tooling/model4adoc/test/ast/plantuml-svg.adoc b/tooling/model4adoc/src/test/resources/org/apache/isis/tooling/model4adoc/test/ast/plantuml-svg.adoc
new file mode 100644
index 0000000..56d9a01
--- /dev/null
+++ b/tooling/model4adoc/src/test/resources/org/apache/isis/tooling/model4adoc/test/ast/plantuml-svg.adoc
@@ -0,0 +1,7 @@
+= Plantuml
+
+[plantuml,alice-and-bob,svg]
+.Alice and Bob
+----
+Bob->Alice : hello
+----