Enhancement of documentation generator.
authorMartin Vitez <mvitez@cisco.com>
Fri, 15 Nov 2013 11:56:45 +0000 (12:56 +0100)
committerMartin Vitez <mvitez@cisco.com>
Fri, 15 Nov 2013 11:56:45 +0000 (12:56 +0100)
Signed-off-by: Martin Vitez <mvitez@cisco.com>
code-generator/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/yangtools/yang/unified/doc/generator/GeneratorImpl.xtend
code-generator/maven-sal-api-gen-plugin/src/test/java/org/opendaylight/yangtools/yang/unified/doc/generator/maven/DocGenTest.java
code-generator/maven-sal-api-gen-plugin/src/test/resources/doc-gen/network-topology@2013-07-12.yang

index 965fd75235dac8705088b8905167fb41b72e756d..78eeaf338388797ba26fef188ec67bcb8dd9de64 100644 (file)
@@ -82,6 +82,8 @@ class GeneratorImpl {
 
         «typeDefinitions(module)»
 
+        «identities(module)»
+
         «groupings(module)»
 
         «dataStore(module)»
@@ -94,6 +96,8 @@ class GeneratorImpl {
 
         «extensions(module)»
 
+        «features(module)»
+
     '''
 
 
@@ -104,31 +108,58 @@ class GeneratorImpl {
         }
         return '''
             <h2>Type Definitions</h2>
-            «list(typedefs)»
-
+            <ul>
             «FOR typedef : typedefs»
-            «typeDefinition(typedef)»
+                <li>
+                    «strong("typedef " + typedef.QName.localName)»
+                    <ul>
+                    «typedef.descAndRef»
+                    «typedef.restrictions»
+                    </ul>
+                </li>
             «ENDFOR»
+            </ul>
         '''
     }
 
-    private def CharSequence typeDefinition(TypeDefinition<?> type) '''
-        «header(type)»
-        «body(type)»
-        «restrictions(type)»
-    '''
+    private def identities(Module module) {
+        if (module.identities.empty) {
+            return '';
+        }
+        return '''
+            <h2>Identities</h2>
+            <ul>
+            «FOR identity : module.identities»
+                <li>
+                    «strong("identity " + identity.QName.localName)»
+                    <ul>
+                    «identity.descAndRef»
+                    «IF identity.baseIdentity != null»
+                        «listItem("base", identity.baseIdentity.QName.localName)»
+                    «ENDIF»
+                    </ul>
+                </li>
+            «ENDFOR»
+            </ul>
+        '''
+    }
 
-    def groupings(Module module) {
+    private def groupings(Module module) {
         if (module.groupings.empty) {
             return '';
         }
         return '''
             <h2>Groupings</h2>
-            «list(module.groupings)»
-
+            <ul>
             «FOR grouping : module.groupings»
-            «headerAndBody(grouping)»
+                <li>
+                    «strong("grouping " + grouping.QName.localName)»
+                    <ul>
+                        «grouping.descAndRef»
+                    </ul>
+                </li>
             «ENDFOR»
+            </ul>
         '''
     }
 
@@ -215,30 +246,25 @@ class GeneratorImpl {
         '''
     }
 
-    def CharSequence headerAndBody(SchemaNode node) '''
-        «header(node)»
-        «body(node)»
-    '''
-
-    def header(SchemaNode type) '''
-        <h3>«type.QName.localName»</h3>
-    '''
-
-    def body(SchemaNode definition) '''
-
-        «paragraphs(definition.description)»
-
-        «definition.reference»
-    '''
-
+    def features(Module module) {
+        if (module.features.empty) {
+            return '';
+        }
+        return '''
+            <h2>Features</h2>
 
-    def list(Set<? extends SchemaNode> definitions) '''
-        <ul>
-        «FOR nodeDef : definitions» 
-            <li>«nodeDef.QName.localName»</li>
-        «ENDFOR»
-        </ul>
-    '''
+            <ul>
+            «FOR feature : module.features»
+                <li>
+                    «strong("feature " + feature.QName.localName)»
+                    <ul>
+                        «feature.descAndRef»
+                    </ul>
+                </li>
+            «ENDFOR»
+            </ul>
+        '''
+    }
 
     def header(Module module) '''
         <h1>«module.name»</h1>
@@ -246,11 +272,11 @@ class GeneratorImpl {
         <h2>Base Information</h2>
         <dl>
             <dt>Prefix</dt>
-            <dd><pre>«module.prefix»</pre></dd>
+            <dd>«pre(module.prefix)»</dd>
             <dt>Namespace</dt>
-            <dd><pre>«module.namespace»</pre></dd>
+            <dd>«pre(module.namespace.toString)»</dd>
             <dt>Revision</dt>
-            <dd>«REVISION_FORMAT.format(module.revision)»</dd>
+            <dd>«pre(REVISION_FORMAT.format(module.revision))»</dd>
             
             «FOR imp : module.imports BEFORE "<dt>Imports</dt>" »
                 <dd>«pre(imp.prefix)» = «pre(imp.moduleName)»</dd>
@@ -258,7 +284,6 @@ class GeneratorImpl {
         </dl>
     '''
 
-
     def process(Module module) {
         throw new UnsupportedOperationException("TODO: auto-generated method stub")
     }
@@ -268,14 +293,14 @@ class GeneratorImpl {
     /* #################### TREE STRUCTURE #################### */
     def dispatch CharSequence tree(Module module) '''
         «strong("module " + module.name)»
-        «module.childNodes.childrenToTree»
+        «module.childNodes.tree»
     '''
 
     def dispatch CharSequence tree(DataNodeContainer node) '''
         «IF node instanceof SchemaNode»
             «(node as SchemaNode).nodeName»
         «ENDIF»
-        «node.childNodes.childrenToTree»
+        «node.childNodes.tree»
     '''
 
     def dispatch CharSequence tree(DataSchemaNode node) '''
@@ -284,10 +309,10 @@ class GeneratorImpl {
 
     def dispatch CharSequence tree(ListSchemaNode node) '''
         «node.nodeName»
-        «node.childNodes.childrenToTree»
+        «node.childNodes.tree»
     '''
 
-    private def CharSequence childrenToTree(Collection<DataSchemaNode> childNodes) '''
+    def dispatch CharSequence tree(Collection<DataSchemaNode> childNodes) '''
         «IF childNodes !== null && !childNodes.empty»
             <ul>
             «FOR child : childNodes»
@@ -305,7 +330,7 @@ class GeneratorImpl {
 
     def dispatch CharSequence tree(AugmentationSchema augment) '''
         <ul>
-            «listItem("Description", augment.description)»
+            «listItem(augment.description)»
             «listItem("Reference", augment.reference)»
             «IF augment.whenCondition !== null»
                 «listItem("When", augment.whenCondition.toString)»
@@ -315,38 +340,24 @@ class GeneratorImpl {
             </li>
             <li>
                 Child nodes
-                «augment.childNodes.childrenToTree»
+                «augment.childNodes.tree»
             </li>
         </ul>
     '''
 
-    private def CharSequence pathToTree(List<QName> path) '''
-        «IF path !== null && !path.empty»
-            <ul>
-            «FOR pathElement : path»
-                <li>
-                    «pathElement.namespace» «pathElement.localName»
-                </li>
-            «ENDFOR»
-            </ul>
-        «ENDIF»
-    '''
-
     def dispatch CharSequence tree(NotificationDefinition notification) '''
         <ul>
-            «listItem("Description", notification.description)»
-            «listItem("Reference", notification.reference)»
+            «notification.descAndRef»
             <li>
                 Child nodes
-                «notification.childNodes.childrenToTree»
+                «notification.childNodes.tree»
             </li>
         </ul>
     '''
 
     def dispatch CharSequence tree(RpcDefinition rpc) '''
         <ul>
-            «listItem("Description", rpc.description)»
-            «listItem("Reference", rpc.reference)»
+            «rpc.descAndRef»
             <li>
                 «rpc.input.tree»
             </li>
@@ -358,13 +369,13 @@ class GeneratorImpl {
 
     def dispatch CharSequence tree(ExtensionDefinition ext) '''
         <ul>
-            «listItem("Description", ext.description)»
-            «listItem("Reference", ext.reference)»
+            «ext.descAndRef»
             «listItem("Argument", ext.argument)»
         </ul>
     '''
 
 
+
     /* #################### RESTRICTIONS #################### */
     private def restrictions(TypeDefinition<?> type) '''
         «type.toLength»
@@ -407,7 +418,7 @@ class GeneratorImpl {
 
     def toLengthStmt(Collection<LengthConstraint> lengths) '''
         «IF lengths != null && !lengths.empty»
-            «strong("Length restrictions")»
+            «listItem("Length restrictions")»
             <ul>
             «FOR length : lengths»
                 <li>
@@ -424,7 +435,7 @@ class GeneratorImpl {
 
     def toRangeStmt(Collection<RangeConstraint> ranges) '''
         «IF ranges != null && !ranges.empty»
-            «strong("Range restrictions")»
+            «listItem("Range restrictions")»
             <ul>
             «FOR range : ranges»
                 <li>
@@ -442,21 +453,24 @@ class GeneratorImpl {
 
 
     /* #################### UTILITY #################### */
-    def strong(String str) '''
-        <strong>«str»</strong>
-    '''
+    private def strong(String str) '''<strong>«str»</strong>'''
+    private def italic(String str) '''<i>«str»</i>'''
+    private def pre(String str) '''<pre>«str»</pre>'''
 
-    def italic(String str) '''
-        <i>«str»</i>
+    def CharSequence descAndRef(SchemaNode node) '''
+        «listItem(node.description)»
+        «listItem("Reference", node.reference)»
     '''
 
-    def pre(String string) '''<pre>«string»</pre>'''
-
-    def paragraphs(String body) '''
-        <p>«body»</p>
+    private def listItem(String value) '''
+        «IF value !== null && !value.empty»
+            <li>
+                «value»
+            </li>
+        «ENDIF»
     '''
 
-    def listItem(String name, String value) '''
+    private def listItem(String name, String value) '''
         «IF value !== null && !value.empty»
             <li>
                 «name»
@@ -469,6 +483,18 @@ class GeneratorImpl {
         «ENDIF»
     '''
 
+    private def CharSequence pathToTree(List<QName> path) '''
+        «IF path !== null && !path.empty»
+            <ul>
+            «FOR pathElement : path»
+                <li>
+                    «pathElement.namespace» «pathElement.localName»
+                </li>
+            «ENDFOR»
+            </ul>
+        «ENDIF»
+    '''
+
     def dispatch addedByInfo(SchemaNode node) '''
     '''
 
@@ -488,7 +514,7 @@ class GeneratorImpl {
         }
     }
 
-    def nodeName(SchemaNode node) '''
+    def dispatch nodeName(SchemaNode node) '''
         «IF node.isAddedBy»
             «italic(node.QName.localName)»«node.addedByInfo»
         «ELSE»
@@ -496,7 +522,7 @@ class GeneratorImpl {
         «ENDIF»
     '''
 
-    def nodeName(ListSchemaNode node) '''
+    def dispatch nodeName(ListSchemaNode node) '''
         «IF node.isAddedBy»
             «italic(node.QName.localName)» «IF node.keyDefinition !== null && !node.keyDefinition.empty»«node.listKeys»«ENDIF»«node.addedByInfo»
         «ELSE»
index 59290bf828d501339dd780c094c2d3789eda430d..7bf8f3ea6c7211985e16b3b304ecfd481c6c0128 100644 (file)
@@ -9,45 +9,34 @@ import java.util.Arrays;
 import java.util.List;
 import java.util.Set;
 
+import org.junit.After;
 import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Test;
-import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator;
-import org.opendaylight.yangtools.sal.binding.generator.impl.BindingGeneratorImpl;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
 import org.opendaylight.yangtools.yang2sources.spi.CodeGenerator;
 
 public class DocGenTest {
-
     public static final String FS = File.separator;
-    static final String BASE_PKG = "org.opendaylight.yang.gen.v1";
-
-    static final String TEST_PATH = "target" + FS + "test";
-    static final File TEST_DIR = new File(TEST_PATH);
-
-    static final File GENERATOR_OUTPUT_DIR = new File(TEST_PATH);
-    static final String COMPILER_OUTPUT_PATH = TEST_PATH + FS + "bin";
-    static final File COMPILER_OUTPUT_DIR = new File(COMPILER_OUTPUT_PATH);
-
+    private static final String TEST_PATH = "target" + FS + "test" + FS + "site";
+    private static final File GENERATOR_OUTPUT_DIR = new File(TEST_PATH);
+    private YangParserImpl parser;
 
-    protected YangParserImpl parser;
-    protected BindingGenerator bindingGenerator;
-
-    @BeforeClass
-    public static void createTestDirs() {
-        if (TEST_DIR.exists()) {
-            deleteTestDir(TEST_DIR);
+    @Before
+    public void init() {
+        if (GENERATOR_OUTPUT_DIR.exists()) {
+            deleteTestDir(GENERATOR_OUTPUT_DIR);
         }
         assertTrue(GENERATOR_OUTPUT_DIR.mkdirs());
-        assertTrue(COMPILER_OUTPUT_DIR.mkdirs());
+        parser = new YangParserImpl();
     }
 
-    @Before
-    public void init() {
-        parser = new YangParserImpl();
-        bindingGenerator = new BindingGeneratorImpl();
+    @After
+    public void cleanUp() {
+        if (GENERATOR_OUTPUT_DIR.exists()) {
+            deleteTestDir(GENERATOR_OUTPUT_DIR);
+        }
     }
 
     @Test
@@ -57,11 +46,9 @@ public class DocGenTest {
         final SchemaContext context = parser.resolveSchemaContext(modulesToBuild);
         final CodeGenerator generator = new DocumentationGeneratorImpl();
         generator.generateSources(context, GENERATOR_OUTPUT_DIR, modulesToBuild);
-
-
     }
 
-    static List<File> getSourceFiles(String path) throws FileNotFoundException {
+    private static List<File> getSourceFiles(String path) throws FileNotFoundException {
         final String resPath = DocGenTest.class.getResource(path).getPath();
         final File sourcesDir = new File(resPath);
         if (sourcesDir.exists()) {
@@ -77,8 +64,7 @@ public class DocGenTest {
         }
     }
 
-
-    static void deleteTestDir(File file) {
+    private static void deleteTestDir(File file) {
         if (file.isDirectory()) {
             File[] filesToDelete = file.listFiles();
             if (filesToDelete != null) {
@@ -91,4 +77,5 @@ public class DocGenTest {
             throw new RuntimeException("Failed to clean up after test");
         }
     }
+
 }
index 835288c3e4c9c9b1ba1d76b624ed3e68ec9c2b4d..fb18be46bca2eb00e8d9542116d990ad82269d9d 100644 (file)
@@ -108,8 +108,10 @@ module network-topology  {
 
     typedef x {
         type binary {
-            length 5..10;
+            length 5..10|15..20|25..30;
         }
+        description "x type description";
+        reference "x type reference";
     }
 
     typedef y {
@@ -118,6 +120,20 @@ module network-topology  {
         }
     }
 
+    identity crypto-alg {
+        description "Base identity from which all crypto algorithms are derived.";
+    }
+
+    identity des {
+        base "crypto-alg";
+        description "DES crypto algorithm";
+    }
+
+    identity des3 {
+        base "crypto-alg";
+        description "Triple DES crypto algorithm";
+    }
+
     grouping tp-attributes {
         description 
             "The data objects needed to define a termination point.
@@ -332,8 +348,18 @@ module network-topology  {
         }
         anyxml reporting-entity;
         container severity {
-            leaf id {
-                type string;
+            list links {
+                container endpoints {
+                    leaf start {
+                        type x;
+                    }
+                    leaf end {
+                        type y;
+                    }
+                }
+                leaf id {
+                    type string;
+                }
             }
         }
     }
@@ -374,6 +400,8 @@ module network-topology  {
     }
 
     rpc rock-the-house {
+        description "This statement is used to define a NETCONF RPC operation.";
+        reference "http://tools.ietf.org/html/rfc6020#section-7.13";
         input {
             leaf zip-code {
                 type string;
@@ -394,4 +422,11 @@ module network-topology  {
         argument "name";
     }
 
+    feature local-storage {
+        description
+            "This feature means the device supports local
+            storage (memory, flash or disk) that can be used to
+            store syslog messages.";
+    }
+
 }