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 2020/12/11 10:21:03 UTC

[isis] branch master updated: ISIS-2473: tooling j2adoc: separation of concerns

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 4de1405  ISIS-2473: tooling j2adoc: separation of concerns
4de1405 is described below

commit 4de14058259efbc3f1599640ecf65ab20913bd41
Author: Andi Huber <ah...@apache.org>
AuthorDate: Fri Dec 11 11:20:49 2020 +0100

    ISIS-2473: tooling j2adoc: separation of concerns
---
 .../apache/isis/tooling/j2adoc/J2AdocContext.java  |  66 ++++-----
 .../org/apache/isis/tooling/j2adoc/J2AdocUnit.java | 162 ++++++---------------
 .../j2adoc/{ => convert}/HtmlToAsciiDoc.java       |   2 +-
 .../tooling/j2adoc/convert/J2AdocConverter.java}   |  39 ++---
 .../J2AdocConverterDefault.java}                   |  26 ++--
 .../isis/tooling/j2adoc/format/UnitFormatter.java} |  51 ++++---
 .../j2adoc/format/UnitFormatterAbstract.java       | 136 +++++++++++++++++
 .../j2adoc/format/UnitFormatterCompact.java}       |  56 ++++---
 .../UnitFormatterWithSourceAndFootNotes.java       |  93 ++++++++++++
 .../isis/tooling/j2adoc/test/J2AdocTest.java       |   7 +-
 .../ast/ClassOrInterfaceDeclarations.java          |   4 +
 .../javamodel/ast/ConstructorDeclarations.java     |   7 +
 .../tooling/javamodel/ast/MethodDeclarations.java  |   7 +
 .../tooling/javamodel/ast/TypeDeclarations.java}   |  27 +---
 14 files changed, 429 insertions(+), 254 deletions(-)

diff --git a/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/J2AdocContext.java b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/J2AdocContext.java
index bd3d4af..031b663 100644
--- a/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/J2AdocContext.java
+++ b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/J2AdocContext.java
@@ -22,13 +22,19 @@ import java.io.File;
 import java.util.ArrayList;
 import java.util.Map;
 import java.util.Optional;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 import org.apache.isis.commons.internal.collections._Maps;
 import org.apache.isis.commons.internal.exceptions._Exceptions;
+import org.apache.isis.tooling.j2adoc.convert.J2AdocConverter;
+import org.apache.isis.tooling.j2adoc.format.UnitFormatter;
+import org.apache.isis.tooling.j2adoc.format.UnitFormatterCompact;
+import org.apache.isis.tooling.j2adoc.format.UnitFormatterWithSourceAndFootNotes;
 
 import lombok.Builder;
+import lombok.Getter;
 import lombok.NonNull;
 import lombok.Value;
 import lombok.val;
@@ -38,30 +44,6 @@ public class J2AdocContext {
 
     private final @NonNull String xrefPageIdFormat;
     
-    /**
-     * name | param-list
-     */
-    @Builder.Default
-    private final @NonNull String constructorFormat = "`%s(%s)`";
-    
-    /**
-     * constructor-generic-type | name | param-list
-     */
-    @Builder.Default
-    private final @NonNull String genericConstructorFormat = "`%s %s(%s)`";
-    
-    /**
-     * return-type | name | param-list
-     */
-    @Builder.Default
-    private final @NonNull String methodFormat = "`%s %s(%s)`";
-    
-    /**
-     * method-generic-type | return-type | name | param-list
-     */
-    @Builder.Default
-    private final @NonNull String genericMethodFormat = "`%s %s %s(%s)`";
-    
     @Builder.Default
     private final @NonNull String memberNameFormat = "[teal]#*%s*#";
     
@@ -74,17 +56,24 @@ public class J2AdocContext {
     @Builder.Default
     private final @NonNull String deprecatedStaticMemberNameFormat = "[line-through gray]#*_%s_*#";
     
-    /**
-     * method | description
-     */
-    @Builder.Default
-    private final @NonNull String memberDescriptionFormat = "\n<.> %s %s\n";
+    // -- CONVERTER
     
-    @Builder.Default
-    private final boolean includeJavaSource = true;
+    private final @NonNull Function<J2AdocContext, J2AdocConverter> converterFactory;
     
-    private final Map<String, J2AdocUnit> unitIndex = _Maps.newTreeMap();
+    @Getter(lazy=true)
+    private final J2AdocConverter converter = getConverterFactory().apply(this);
+    
+    // -- FORMATTER
+    
+    private final @NonNull Function<J2AdocContext, UnitFormatter> formatterFactory;
+    
+    @Getter(lazy=true)
+    private final UnitFormatter formatter = getFormatterFactory().apply(this);
 
+    // -- UNIT INDEX
+    
+    private final Map<String, J2AdocUnit> unitIndex = _Maps.newTreeMap();
+    
     public J2AdocContext add(final @NonNull J2AdocUnit unit) {
         val previousKey = unitIndex.put(unit.getName(), unit);
         if(previousKey!=null) {
@@ -115,17 +104,16 @@ public class J2AdocContext {
     // -- PREDEFINED FORMATS
     
     public static J2AdocContextBuilder javaSourceWithFootNotesFormat() {
-        return J2AdocContext.builder();
+        return J2AdocContext.builder()
+                .converterFactory(J2AdocConverter::createDefault)
+                .formatterFactory(UnitFormatterWithSourceAndFootNotes::new)
+                ;
     }
     
     public static J2AdocContextBuilder compactFormat() {
         return J2AdocContext.builder()
-                .constructorFormat("`%1$s(%2$s)`") // name | param-list)
-                .genericConstructorFormat("`%2$s%1$s(%3$s)`") //  method-generic-type | name | param-list)
-                .methodFormat("`%2$s(%3$s)` : `%1$s`") //  return-type | name | param-list)
-                .genericMethodFormat("`%3$s%1$s(%4$s)` : `%2$s`") //  method-generic-type | return-type | name | param-list)
-                .memberDescriptionFormat("\n* %s\n%s\n") // method | description
-                .includeJavaSource(false)
+                .converterFactory(J2AdocConverter::createDefault)
+                .formatterFactory(UnitFormatterCompact::new)
                 ;        
     }
     
diff --git a/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/J2AdocUnit.java b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/J2AdocUnit.java
index 48cab30..3983886 100644
--- a/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/J2AdocUnit.java
+++ b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/J2AdocUnit.java
@@ -19,10 +19,14 @@
 package org.apache.isis.tooling.j2adoc;
 
 import java.io.File;
+import java.util.Optional;
 import java.util.stream.Stream;
 
 import com.github.javaparser.StaticJavaParser;
 import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
+import com.github.javaparser.ast.body.ConstructorDeclaration;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.javadoc.Javadoc;
 
 import org.asciidoctor.ast.Document;
 
@@ -31,19 +35,20 @@ import org.apache.isis.tooling.j2adoc.util.AsciiDocIncludeTagFilter;
 import org.apache.isis.tooling.javamodel.ast.ClassOrInterfaceDeclarations;
 import org.apache.isis.tooling.javamodel.ast.CompilationUnits;
 import org.apache.isis.tooling.javamodel.ast.Javadocs;
-import org.apache.isis.tooling.model4adoc.AsciiDocFactory;
+import org.apache.isis.tooling.javamodel.ast.TypeDeclarations;
 
+import lombok.Getter;
 import lombok.NonNull;
-import lombok.Value;
+import lombok.RequiredArgsConstructor;
 import lombok.val;
 import lombok.extern.log4j.Log4j2;
 
-@Value
+@RequiredArgsConstructor
 @Log4j2
-public class J2AdocUnit {
+public final class J2AdocUnit {
 
     private final ClassOrInterfaceDeclaration td;
-
+    
     public static Stream<J2AdocUnit> parse(final @NonNull File sourceFile) {
 
         if("package-info.java".equals(sourceFile.getName())) {
@@ -61,7 +66,7 @@ public class J2AdocUnit {
             
             return Stream.of(cu)
             .flatMap(CompilationUnits::streamPublicTypeDeclarations)
-            .filter(J2AdocUnits::hasIndexDirective)
+            .filter(TypeDeclarations::hasIndexDirective)
             .map(J2AdocUnit::new);
 
         } catch (Exception e) {
@@ -70,130 +75,47 @@ public class J2AdocUnit {
         }
 
     }
-    
-    public String getName() {
-        return ClassOrInterfaceDeclarations.name(td);
-    }
 
-    public String getAsciiDocXref(
-            final @NonNull J2AdocContext j2aContext) {
-        val toAdocConverter = JavaToAsciiDoc.of(j2aContext);
-        return toAdocConverter.xref(this);
-    }
+    /**
+     * Returns the recursively resolved (nested) type name. 
+     * Same as {@link #getSimpleName()} if type is not nested. 
+     */
+    @Getter(lazy = true)
+    private final String name = ClassOrInterfaceDeclarations.name(td);
     
-    public Document toAsciiDoc(
-            final @NonNull J2AdocContext j2aContext) {
-        
-        val doc = AsciiDocFactory.doc();
-        
-        val introBlock = AsciiDocFactory.block(doc);
-        val javaSourceBlock = AsciiDocFactory.block(doc);
-        val methodDescriptionBlock = AsciiDocFactory.block(doc);
-        
-        val mds = ClassOrInterfaceDeclarations.streamPublicMethodDeclarations(td)
+    @Getter(lazy = true)
+    private final String simpleName = td.getNameAsString();
+    
+    @Getter(lazy = true)
+    private final String declarationKeyword = td.isInterface()
+            ? "interface"
+            : "class";
+    
+    @Getter(lazy = true)
+    private final Can<ConstructorDeclaration> publicConstructorDeclarations =
+        ClassOrInterfaceDeclarations.streamPublicConstructorDeclarations(td)
                 .filter(Javadocs::presentAndNotHidden)
                 .collect(Can.toCan());
-        
-        val cds = ClassOrInterfaceDeclarations.streamPublicConstructorDeclarations(td)
+    
+    @Getter(lazy = true)
+    private final Can<MethodDeclaration> publicMethodDeclarations =
+        ClassOrInterfaceDeclarations.streamPublicMethodDeclarations(td)
                 .filter(Javadocs::presentAndNotHidden)
                 .collect(Can.toCan());
-        
-        
-        val toAdocConverter = JavaToAsciiDoc.of(j2aContext);
-        
-        // -- title
-        
-        val title = String.format("%s : _%s_\n\n", 
-                getName(),
-                getDeclarationKeyword());
-        
-        doc.setTitle(title);
-
-        // -- intro
-        
-        td.getJavadoc().ifPresent(javadoc->{
-            introBlock.setSource(toAdocConverter.javadoc(javadoc, 0));    
-        });
-        
-        // -- java content
-        
-        if(j2aContext.isIncludeJavaSource()) {
-        
-            val java = new StringBuilder();
-            
-            java.append(String.format("%s %s {\n", 
-                    getDeclarationKeyword(), 
-                    td.getName().asString()));
-            
-            
-            cds.forEach(cd->{
-                
-                java.append(String.format("\n  %s // <.>\n", 
-                        J2AdocUnits.toNormalizedConstructorDeclaration(cd)));
-                
-            });
-            
-            mds.forEach(md->{
     
-                java.append(String.format("\n  %s // <.>\n", 
-                        J2AdocUnits.toNormalizedMethodDeclaration(md)));
-                
-            });
+    @Getter(lazy = true)
+    private final Optional<Javadoc> javadoc = td.getJavadoc();
     
-            java.append("}\n");
-            
-            javaSourceBlock.setSource(
-                    AsciiDocFactory.SourceFactory.java(java.toString(), td.getName().asString()));
-        }
-            
-        // -- constructor and method descriptions
-        
-        val methodDescriptions = new StringBuilder();
-        
-        cds.forEach(cd->{
-            
-            cd.getJavadoc()
-            .ifPresent(javadoc->{
-                methodDescriptions.append(String.format(j2aContext.getMemberDescriptionFormat(),
-                        toAdocConverter.constructorDeclaration(cd),
-                        toAdocConverter.javadoc(javadoc, 1)));
-            });
-            
-        });
-        
-        mds.forEach(md->{
-            
-            md.getJavadoc()
-            .ifPresent(javadoc->{
-                methodDescriptions.append(String.format(j2aContext.getMemberDescriptionFormat(),
-                        toAdocConverter.methodDeclaration(md),
-                        toAdocConverter.javadoc(javadoc, 1)));
-            });
-            
-        });
-        
-        methodDescriptionBlock.setSource(methodDescriptions.toString());
-        
-        return doc;
-        
-//        try {
-//
-//            return AsciiDocWriter.toString(doc);
-//        } catch (Exception e) {
-//            e.printStackTrace();
-//            return "ERROR: " + e.getMessage();
-//        }
-        
-    }
-
-    // -- HELPER
+    public String getAsciiDocXref(
+            final @NonNull J2AdocContext j2aContext) {
 
-    private String getDeclarationKeyword() {
-        return td.isInterface()
-                ? "interface"
-                : "class";
+        return j2aContext.getConverter().xref(this);
+    }
+    
+    public Document toAsciiDoc(
+            final @NonNull J2AdocContext j2aContext) {
+        return j2aContext.getFormatter().apply(this);
     }
-
 
 
 }
diff --git a/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/HtmlToAsciiDoc.java b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/convert/HtmlToAsciiDoc.java
similarity index 99%
rename from tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/HtmlToAsciiDoc.java
rename to tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/convert/HtmlToAsciiDoc.java
index a4a6910..da5deb1 100644
--- a/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/HtmlToAsciiDoc.java
+++ b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/convert/HtmlToAsciiDoc.java
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.isis.tooling.j2adoc;
+package org.apache.isis.tooling.j2adoc.convert;
 
 import java.util.Stack;
 
diff --git a/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/ConstructorDeclarations.java b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/convert/J2AdocConverter.java
similarity index 57%
copy from tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/ConstructorDeclarations.java
copy to tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/convert/J2AdocConverter.java
index da43396..6e24b9b 100644
--- a/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/ConstructorDeclarations.java
+++ b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/convert/J2AdocConverter.java
@@ -16,28 +16,33 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.isis.tooling.javamodel.ast;
+package org.apache.isis.tooling.j2adoc.convert;
 
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
 import com.github.javaparser.ast.body.ConstructorDeclaration;
+import com.github.javaparser.ast.body.MethodDeclaration;
+import com.github.javaparser.javadoc.Javadoc;
+
+import org.apache.isis.tooling.j2adoc.J2AdocContext;
+import org.apache.isis.tooling.j2adoc.J2AdocUnit;
 
 import lombok.NonNull;
 
-public final class ConstructorDeclarations {
-
-    public static boolean isEffectivePublic(
-            final @NonNull ConstructorDeclaration cd, final @NonNull ClassOrInterfaceDeclaration td) {
-        
-        if(td.isInterface()) {
-            return true;
-        }
-       
-        //TODO effective public requires more context, eg. is the container an interface 
-        return !cd.isPrivate() 
-                && !cd.isAbstract() 
-                && !cd.isProtected()
-                //&& !md.isDefault()
-                ;
+public interface J2AdocConverter {
+
+    String javadoc(Javadoc javadoc, int level);
+
+    String constructorDeclaration(ConstructorDeclaration cd);
+
+    String methodDeclaration(MethodDeclaration md);
+    
+    String xref(@NonNull J2AdocUnit unit);
+    
+    // -- FACTORIES
+    
+    public static J2AdocConverter createDefault(final @NonNull J2AdocContext context) {
+        return J2AdocConverterDefault.of(context);
     }
+
     
+
 }
diff --git a/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/JavaToAsciiDoc.java b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/convert/J2AdocConverterDefault.java
similarity index 91%
rename from tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/JavaToAsciiDoc.java
rename to tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/convert/J2AdocConverterDefault.java
index b9c3c05..305971e 100644
--- a/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/JavaToAsciiDoc.java
+++ b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/convert/J2AdocConverterDefault.java
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.isis.tooling.j2adoc;
+package org.apache.isis.tooling.j2adoc.convert;
 
 import java.util.stream.Collectors;
 
@@ -40,6 +40,8 @@ import org.jsoup.Jsoup;
 
 import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal._Constants;
+import org.apache.isis.tooling.j2adoc.J2AdocContext;
+import org.apache.isis.tooling.j2adoc.J2AdocUnit;
 import org.apache.isis.tooling.javamodel.ast.Javadocs;
 import org.apache.isis.tooling.model4adoc.AsciiDocFactory;
 import org.apache.isis.tooling.model4adoc.AsciiDocWriter;
@@ -49,10 +51,11 @@ import lombok.Value;
 import lombok.val;
 
 @Value(staticConstructor = "of")
-final class JavaToAsciiDoc {
+final class J2AdocConverterDefault implements J2AdocConverter {
 
     private final J2AdocContext j2aContext;
     
+    @Override
     public String constructorDeclaration(final @NonNull ConstructorDeclaration cd) {
         val isDeprecated = cd.getAnnotations().stream()
                 .anyMatch(a->a.getNameAsString().equals("Deprecated"))
@@ -65,14 +68,14 @@ final class JavaToAsciiDoc {
                         ? j2aContext.getDeprecatedStaticMemberNameFormat()
                         : j2aContext.getDeprecatedMemberNameFormat()
                 : cd.isStatic()
-                    ? j2aContext.getStaticMemberNameFormat()
-                    : j2aContext.getMemberNameFormat();
+                        ? j2aContext.getStaticMemberNameFormat()
+                        : j2aContext.getMemberNameFormat();
 
         val isGenericMember = cd.getTypeParameters().isNonEmpty();
         
         val constructorFormat = isGenericMember
-                ? j2aContext.getGenericConstructorFormat()
-                : j2aContext.getConstructorFormat();
+                ? j2aContext.getFormatter().getGenericConstructorFormat()
+                : j2aContext.getFormatter().getConstructorFormat();
         
         val args = Can.<Object>of(
                 isGenericMember ? typeParamters(cd.getTypeParameters()) : null,  // Cans do ignored null 
@@ -86,6 +89,7 @@ final class JavaToAsciiDoc {
         return String.format(constructorFormat, args.toArray(_Constants.emptyObjects));
     }
 
+    @Override
     public String methodDeclaration(final @NonNull MethodDeclaration md) {
         
         val isDeprecated = md.getAnnotations().stream()
@@ -99,14 +103,14 @@ final class JavaToAsciiDoc {
                         ? j2aContext.getDeprecatedStaticMemberNameFormat()
                         : j2aContext.getDeprecatedMemberNameFormat()
                 : md.isStatic()
-                    ? j2aContext.getStaticMemberNameFormat()
-                    : j2aContext.getMemberNameFormat();
+                        ? j2aContext.getStaticMemberNameFormat()
+                        : j2aContext.getMemberNameFormat();
 
         val isGenericMember = md.getTypeParameters().isNonEmpty();
         
         val methodFormat = isGenericMember
-                ? j2aContext.getGenericMethodFormat()
-                : j2aContext.getMethodFormat();
+                ? j2aContext.getFormatter().getGenericMethodFormat()
+                : j2aContext.getFormatter().getMethodFormat();
         
         val args = Can.<Object>of(
                 isGenericMember ? typeParamters(md.getTypeParameters()) : null,  // Cans do ignored null 
@@ -168,6 +172,7 @@ final class JavaToAsciiDoc {
                 p.getNameAsString());
     }
     
+    @Override
     public String javadoc(final @NonNull Javadoc javadoc, final int level) {
 
         val adoc = AsciiDocFactory.doc();
@@ -204,6 +209,7 @@ final class JavaToAsciiDoc {
         }
     }
     
+    @Override
     public String xref(final @NonNull J2AdocUnit unit) {
         return String.format("xref:%s[%s]", 
                 String.format(j2aContext.getXrefPageIdFormat(), unit.getName()), 
diff --git a/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/ConstructorDeclarations.java b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/format/UnitFormatter.java
similarity index 53%
copy from tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/ConstructorDeclarations.java
copy to tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/format/UnitFormatter.java
index da43396..e1c8239 100644
--- a/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/ConstructorDeclarations.java
+++ b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/format/UnitFormatter.java
@@ -16,28 +16,41 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.isis.tooling.javamodel.ast;
+package org.apache.isis.tooling.j2adoc.format;
 
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.ast.body.ConstructorDeclaration;
+import java.util.function.Function;
 
-import lombok.NonNull;
+import org.asciidoctor.ast.Document;
 
-public final class ConstructorDeclarations {
+import org.apache.isis.tooling.j2adoc.J2AdocUnit;
+
+public interface UnitFormatter 
+extends Function<J2AdocUnit, Document> {
+
+    /**
+     * name | param-list
+     */
+    String getConstructorFormat();
+    
+    /**
+     * constructor-generic-type | name | param-list
+     */
+    String getGenericConstructorFormat(); 
+    
+    /**
+     * return-type | name | param-list
+     */
+    String getMethodFormat();
+    
+    /**
+     * method-generic-type | return-type | name | param-list
+     */
+    String getGenericMethodFormat();
+    
+    /**
+     * member | description
+     */
+    String getMemberDescriptionFormat();
 
-    public static boolean isEffectivePublic(
-            final @NonNull ConstructorDeclaration cd, final @NonNull ClassOrInterfaceDeclaration td) {
-        
-        if(td.isInterface()) {
-            return true;
-        }
-       
-        //TODO effective public requires more context, eg. is the container an interface 
-        return !cd.isPrivate() 
-                && !cd.isAbstract() 
-                && !cd.isProtected()
-                //&& !md.isDefault()
-                ;
-    }
     
 }
diff --git a/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/format/UnitFormatterAbstract.java b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/format/UnitFormatterAbstract.java
new file mode 100644
index 0000000..98414ab
--- /dev/null
+++ b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/format/UnitFormatterAbstract.java
@@ -0,0 +1,136 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.tooling.j2adoc.format;
+
+import java.util.Optional;
+
+import org.asciidoctor.ast.Document;
+
+import org.apache.isis.tooling.j2adoc.J2AdocContext;
+import org.apache.isis.tooling.j2adoc.J2AdocUnit;
+import org.apache.isis.tooling.j2adoc.convert.J2AdocConverter;
+import org.apache.isis.tooling.model4adoc.AsciiDocFactory;
+
+import lombok.AccessLevel;
+import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
+import lombok.val;
+
+@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
+public abstract class UnitFormatterAbstract 
+implements UnitFormatter {
+    
+    private final @NonNull J2AdocContext j2aContext;
+    
+    protected Optional<String> title(final J2AdocUnit unit) {
+        return Optional.of(
+                String.format("%s : _%s_\n\n", 
+                        unit.getName(),
+                        unit.getDeclarationKeyword()));
+    }
+    
+    protected Optional<String> intro(final J2AdocUnit unit) {
+        return unit.getJavadoc()
+                .map(javadoc->getConverter().javadoc(javadoc, 0));    
+        
+    }
+    
+    protected Optional<String> javaSource(final J2AdocUnit unit) {
+        return Optional.empty();
+    }
+    
+    protected Optional<String> memberDescriptions(final J2AdocUnit unit) {
+        
+        val sb = new StringBuilder();
+        
+        unit.getPublicConstructorDeclarations().forEach(cd->{
+            
+            cd.getJavadoc()
+            .ifPresent(javadoc->{
+                sb.append(String.format(getContext().getFormatter().getMemberDescriptionFormat(),
+                        getConverter().constructorDeclaration(cd),
+                        getConverter().javadoc(javadoc, 1)));
+            });
+            
+        });
+        
+        unit.getPublicMethodDeclarations().forEach(md->{
+            
+            md.getJavadoc()
+            .ifPresent(javadoc->{
+                sb.append(String.format(getContext().getFormatter().getMemberDescriptionFormat(),
+                        getConverter().methodDeclaration(md),
+                        getConverter().javadoc(javadoc, 1)));
+            });
+            
+        });
+        
+        return Optional.of(sb.toString());
+    }
+    
+    protected Optional<String> outro(final J2AdocUnit unit) {
+        return Optional.empty();
+    }
+    
+
+    @Override
+    public Document apply(final J2AdocUnit unit) {
+        
+        val doc = AsciiDocFactory.doc();
+        
+        // -- title
+        
+        title(unit)
+        .ifPresent(doc::setTitle);
+
+        // -- intro
+        
+        intro(unit)
+        .ifPresent(source->AsciiDocFactory.block(doc).setSource(source));
+        
+        // -- java source
+        
+        javaSource(unit)
+        .ifPresent(source->AsciiDocFactory.block(doc).setSource(source));
+            
+        // -- member descriptions
+        
+        memberDescriptions(unit)
+        .ifPresent(source->AsciiDocFactory.block(doc).setSource(source));
+        
+        // -- outro
+        
+        outro(unit)
+        .ifPresent(source->AsciiDocFactory.block(doc).setSource(source));
+        
+        return doc;
+    }
+    
+    // -- DEPENDENCIES
+    
+    protected final J2AdocContext getContext() {
+        return j2aContext;
+    }
+    
+    protected final J2AdocConverter getConverter() {
+        return j2aContext.getConverter();
+    }
+
+
+}
diff --git a/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/ConstructorDeclarations.java b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/format/UnitFormatterCompact.java
similarity index 52%
copy from tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/ConstructorDeclarations.java
copy to tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/format/UnitFormatterCompact.java
index da43396..03e0ff6 100644
--- a/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/ConstructorDeclarations.java
+++ b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/format/UnitFormatterCompact.java
@@ -16,28 +16,40 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.isis.tooling.javamodel.ast;
-
-import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
-import com.github.javaparser.ast.body.ConstructorDeclaration;
-
-import lombok.NonNull;
-
-public final class ConstructorDeclarations {
-
-    public static boolean isEffectivePublic(
-            final @NonNull ConstructorDeclaration cd, final @NonNull ClassOrInterfaceDeclaration td) {
-        
-        if(td.isInterface()) {
-            return true;
-        }
-       
-        //TODO effective public requires more context, eg. is the container an interface 
-        return !cd.isPrivate() 
-                && !cd.isAbstract() 
-                && !cd.isProtected()
-                //&& !md.isDefault()
-                ;
+package org.apache.isis.tooling.j2adoc.format;
+
+import org.apache.isis.tooling.j2adoc.J2AdocContext;
+
+public class UnitFormatterCompact 
+extends UnitFormatterAbstract {
+
+    public UnitFormatterCompact(J2AdocContext j2aContext) {
+        super(j2aContext);
+    }
+
+    @Override
+    public String getConstructorFormat() {
+        return "`%1$s(%2$s)`";
     }
     
+    @Override
+    public String getGenericConstructorFormat() {
+        return "`%2$s%1$s(%3$s)`";
+    }
+
+    @Override
+    public String getMethodFormat() {
+        return "`%2$s(%3$s)` : `%1$s`";
+    }
+
+    @Override
+    public String getGenericMethodFormat() {
+        return "`%3$s%1$s(%4$s)` : `%2$s`";
+    }
+
+    @Override
+    public String getMemberDescriptionFormat() {
+        return "\n* %s\n%s\n";
+    }
+
 }
diff --git a/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/format/UnitFormatterWithSourceAndFootNotes.java b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/format/UnitFormatterWithSourceAndFootNotes.java
new file mode 100644
index 0000000..51e6357
--- /dev/null
+++ b/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/format/UnitFormatterWithSourceAndFootNotes.java
@@ -0,0 +1,93 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.tooling.j2adoc.format;
+
+import java.util.Optional;
+
+import org.apache.isis.tooling.j2adoc.J2AdocContext;
+import org.apache.isis.tooling.j2adoc.J2AdocUnit;
+import org.apache.isis.tooling.javamodel.ast.ConstructorDeclarations;
+import org.apache.isis.tooling.javamodel.ast.MethodDeclarations;
+import org.apache.isis.tooling.model4adoc.AsciiDocFactory;
+
+import lombok.val;
+
+public class UnitFormatterWithSourceAndFootNotes 
+extends UnitFormatterAbstract {
+
+    public UnitFormatterWithSourceAndFootNotes(final J2AdocContext j2aContext) {
+        super(j2aContext);
+    }
+    
+    protected Optional<String> javaSource(final J2AdocUnit unit) {
+        
+        val java = new StringBuilder();
+        
+        java.append(String.format("%s %s {\n", 
+                unit.getDeclarationKeyword(), 
+                unit.getSimpleName()));
+        
+        unit.getPublicConstructorDeclarations().forEach(cd->{
+            
+            java.append(String.format("\n  %s // <.>\n", 
+                    ConstructorDeclarations.toNormalizedConstructorDeclaration(cd)));
+            
+        });
+        
+        unit.getPublicMethodDeclarations().forEach(md->{
+
+            java.append(String.format("\n  %s // <.>\n", 
+                    MethodDeclarations.toNormalizedMethodDeclaration(md)));
+            
+        });
+
+        java.append("}\n");
+        
+        
+        return Optional.of(
+                AsciiDocFactory.SourceFactory.java(java.toString(), unit.getName()));
+            
+    }
+
+    @Override
+    public String getConstructorFormat() {
+        return "`%s(%s)`";
+    }
+
+    @Override
+    public String getGenericConstructorFormat() {
+        return "`%s %s(%s)`";
+    }
+
+    @Override
+    public String getMethodFormat() {
+        return "`%s %s(%s)`";
+    }
+
+    @Override
+    public String getGenericMethodFormat() {
+        return "`%s %s %s(%s)`";
+    }
+
+    @Override
+    public String getMemberDescriptionFormat() {
+        return "\n<.> %s %s\n";
+    }
+
+}
diff --git a/tooling/java2adoc/src/test/java/org/apache/isis/tooling/j2adoc/test/J2AdocTest.java b/tooling/java2adoc/src/test/java/org/apache/isis/tooling/j2adoc/test/J2AdocTest.java
index 8a77a21..c8512ac 100644
--- a/tooling/java2adoc/src/test/java/org/apache/isis/tooling/j2adoc/test/J2AdocTest.java
+++ b/tooling/java2adoc/src/test/java/org/apache/isis/tooling/j2adoc/test/J2AdocTest.java
@@ -64,9 +64,12 @@ class J2AdocTest {
         .forEach(j2aContext::add);
         
         j2aContext.streamUnits()
-        .forEach(unit->{
+        .map(unit->unit.toAsciiDoc(j2aContext))
+        .forEach(adoc->{
             
-            System.out.println(unit.toAsciiDoc(j2aContext));
+            System.out.println(adoc);
+            
+            //AsciiDocWriter.print(adoc);
             System.out.println();
 
         });
diff --git a/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/ClassOrInterfaceDeclarations.java b/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/ClassOrInterfaceDeclarations.java
index 751dc6e..980448f 100644
--- a/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/ClassOrInterfaceDeclarations.java
+++ b/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/ClassOrInterfaceDeclarations.java
@@ -52,6 +52,10 @@ public final class ClassOrInterfaceDeclarations {
                 .filter(md->MethodDeclarations.isEffectivePublic(md, typeDeclaration));
     }
 
+    /**
+     * Returns the recursively resolved (nested) type name. 
+     * Same as {@link #getSimpleName()} if type is not nested. 
+     */
     public static String name(
             final @NonNull ClassOrInterfaceDeclaration td) {
         String name = td.getNameAsString(); 
diff --git a/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/ConstructorDeclarations.java b/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/ConstructorDeclarations.java
index da43396..1048fad 100644
--- a/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/ConstructorDeclarations.java
+++ b/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/ConstructorDeclarations.java
@@ -40,4 +40,11 @@ public final class ConstructorDeclarations {
                 ;
     }
     
+    /**
+     * Returns given {@link ConstructorDeclaration} as normal text, without formatting.
+     */
+    public static String toNormalizedConstructorDeclaration(final @NonNull ConstructorDeclaration cd) {
+        return cd.getDeclarationAsString(false, false, true).trim();
+    }
+    
 }
diff --git a/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/MethodDeclarations.java b/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/MethodDeclarations.java
index ec028b0..c5a85f0 100644
--- a/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/MethodDeclarations.java
+++ b/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/MethodDeclarations.java
@@ -40,4 +40,11 @@ public final class MethodDeclarations {
                 ;
     }
     
+    /**
+     * Returns given {@link MethodDeclaration} as normal text, without formatting.
+     */
+    public static String toNormalizedMethodDeclaration(final @NonNull MethodDeclaration md) {
+        return md.getDeclarationAsString(false, false, true).trim();
+    }
+    
 }
diff --git a/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/J2AdocUnits.java b/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/TypeDeclarations.java
similarity index 62%
rename from tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/J2AdocUnits.java
rename to tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/TypeDeclarations.java
index 781de0b..66d80eb 100644
--- a/tooling/java2adoc/src/main/java/org/apache/isis/tooling/j2adoc/J2AdocUnits.java
+++ b/tooling/javamodel/src/main/java/org/apache/isis/tooling/javamodel/ast/TypeDeclarations.java
@@ -16,18 +16,14 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.isis.tooling.j2adoc;
+package org.apache.isis.tooling.javamodel.ast;
 
-import com.github.javaparser.ast.body.ConstructorDeclaration;
-import com.github.javaparser.ast.body.MethodDeclaration;
 import com.github.javaparser.ast.body.TypeDeclaration;
 
-import org.apache.isis.tooling.javamodel.ast.Javadocs;
-
 import lombok.NonNull;
 import lombok.val;
 
-final class J2AdocUnits {
+public final class TypeDeclarations {
 
     /**
      * Whether to include given {@link TypeDeclaration} with the index.
@@ -35,7 +31,7 @@ final class J2AdocUnits {
      * This is decided base on whether the type's java-doc has a
      * {@literal @since} tag that contains the literal {@literal {@index}}. 
      */
-    static boolean hasIndexDirective(final @NonNull TypeDeclaration<?> td) {
+    public static boolean hasIndexDirective(final @NonNull TypeDeclaration<?> td) {
         return td.getJavadoc()
         .map(javadoc->{
         
@@ -48,21 +44,4 @@ final class J2AdocUnits {
         .orElse(false);
     }
     
-    /**
-     * Returns given {@link ConstructorDeclaration} as normal text, without formatting.
-     */
-    static String toNormalizedConstructorDeclaration(final @NonNull ConstructorDeclaration cd) {
-        return cd.getDeclarationAsString(false, false, true).trim();
-    }
-    
-    /**
-     * Returns given {@link MethodDeclaration} as normal text, without formatting.
-     */
-    static String toNormalizedMethodDeclaration(final @NonNull MethodDeclaration md) {
-        return md.getDeclarationAsString(false, false, true).trim();
-    }
-    
-    
-    
-    
 }