Use YangTextSnippet for generation 31/68031/14
authorRobert Varga <robert.varga@pantheon.tech>
Wed, 14 Feb 2018 19:15:43 +0000 (20:15 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Tue, 13 Mar 2018 14:54:07 +0000 (15:54 +0100)
YangTextSnippet provides an efficient and correct replacement for
YangTemplate. This patch switches to using it, improving generated
class comments.

JIRA: MDSAL-301
Change-Id: I2058eec8e91bcba9356fef49a13c66199a479ed2
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
binding/mdsal-binding-generator-api/src/main/java/org/opendaylight/mdsal/binding/model/api/YangSourceDefinition.java
binding/mdsal-binding-generator-impl/src/main/java/org/opendaylight/mdsal/binding/generator/impl/CodegenTypeGenerator.java
binding/mdsal-binding-java-api-generator/pom.xml
binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/BaseTemplate.xtend
binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/YangTemplate.xtend [deleted file]

index c2b3293e538239deddd052d78247293423d922f3..3304325602e7e33685b60ef63d3cb92e2a8d6de4 100644 (file)
@@ -14,10 +14,16 @@ import com.google.common.annotations.Beta;
 import com.google.common.collect.ImmutableList;
 import java.util.Collection;
 import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.opendaylight.yangtools.yang.model.api.DocumentedNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ModuleEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ModuleStatement;
 
 /**
  * DTO capturing the YANG source definition which lead to a {@link GeneratedType} being emitted.
@@ -30,51 +36,86 @@ public abstract class YangSourceDefinition {
     public static final class Multiple extends YangSourceDefinition {
         private final List<? extends SchemaNode> nodes;
 
-        Multiple(final Module module, final Collection<? extends SchemaNode> nodes) {
+        Multiple(final ModuleEffectiveStatement module, final Collection<? extends SchemaNode> nodes) {
             super(module);
             this.nodes = ImmutableList.copyOf(nodes);
         }
 
         /**
-         * Return the defining SchemaNodes.
+         * Return the defining SchemaNodes. Each node is guaranteed to implement {@link EffectiveStatement} and have
+         * a corresponding declared statement.
          *
          * @return defining SchemaNodes, guaranteed to be non-empty
          */
         public List<? extends SchemaNode> getNodes() {
-            return nodes;
+            return nodes.stream().filter(node -> {
+                return node instanceof EffectiveStatement && ((EffectiveStatement<?, ?>) node).getDeclared() != null;
+            }).collect(Collectors.toList());
         }
     }
 
     public static final class Single extends YangSourceDefinition {
         private final DocumentedNode node;
 
-        Single(final Module module, final DocumentedNode node) {
+        Single(final ModuleEffectiveStatement module, final DocumentedNode node) {
             super(module);
             this.node = requireNonNull(node);
         }
 
+        /**
+         * Return the defining DocumentedNode. The node is guaranteed to implement {@link EffectiveStatement} and have
+         * a corresponding declared statement.
+         *
+         * @return defining SchemaNodes, guaranteed to be non-empty
+         */
         public DocumentedNode getNode() {
             return node;
         }
     }
 
-    private final Module module;
+    private final ModuleEffectiveStatement module;
 
-    private YangSourceDefinition(final Module module) {
+    private YangSourceDefinition(final ModuleEffectiveStatement module) {
         this.module = requireNonNull(module);
     }
 
-    public static YangSourceDefinition of(final Module module) {
-        return new Single(module, module);
+    public static Optional<YangSourceDefinition> of(final Module module) {
+        if (module instanceof ModuleEffectiveStatement) {
+            final ModuleEffectiveStatement effective = (ModuleEffectiveStatement) module;
+            final ModuleStatement declared = effective.getDeclared();
+            if (declared != null) {
+                return Optional.of(new Single(effective, module));
+            }
+        }
+        return Optional.empty();
     }
 
-    public static YangSourceDefinition of(final Module module, final SchemaNode node) {
-        return new Single(module, node);
+    public static Optional<YangSourceDefinition> of(final Module module, final SchemaNode node) {
+        if (module instanceof ModuleEffectiveStatement) {
+            final ModuleEffectiveStatement effective = (ModuleEffectiveStatement) module;
+            if (node instanceof EffectiveStatement) {
+                final DeclaredStatement<?> declared = ((EffectiveStatement<?, ?>) node).getDeclared();
+                if (declared != null) {
+                    return Optional.of(new Single(effective, node));
+                }
+            }
+        }
+        return Optional.empty();
     }
 
-    public static YangSourceDefinition of(final Module module, final Collection<? extends SchemaNode> nodes) {
+    public static Optional<YangSourceDefinition> of(final Module module, final Collection<? extends SchemaNode> nodes) {
         checkArgument(!nodes.isEmpty());
-        return new Multiple(module, nodes);
+
+        if (module instanceof ModuleEffectiveStatement) {
+            final ModuleEffectiveStatement effective = (ModuleEffectiveStatement) module;
+            final boolean anyDeclared = nodes.stream().anyMatch(node -> {
+                return node instanceof EffectiveStatement && ((EffectiveStatement<?, ?>) node).getDeclared() != null;
+            });
+            if (anyDeclared) {
+                return Optional.of(new Multiple(effective, nodes));
+            }
+        }
+        return Optional.empty();
     }
 
     /**
@@ -82,7 +123,7 @@ public abstract class YangSourceDefinition {
      *
      * @return Defining YANG module.
      */
-    public final Module getModule() {
+    public final ModuleEffectiveStatement getModule() {
         return module;
     }
 }
index 2affbe04c55232586e8f092b67d368daef2eea34..51d84564faeaccaa947ee5c2b715f55025d5b352 100644 (file)
@@ -45,7 +45,7 @@ final class CodegenTypeGenerator extends AbstractTypeGenerator {
     @Override
     void addCodegenInformation(final GeneratedTypeBuilderBase<?> genType, final Module module,
             final SchemaNode node) {
-        genType.setYangSourceDefinition(YangSourceDefinition.of(module, node));
+        YangSourceDefinition.of(module, node).ifPresent(genType::setYangSourceDefinition);
         TypeComments.description(node).ifPresent(genType::addComment);
         node.getDescription().ifPresent(genType::setDescription);
         node.getReference().ifPresent(genType::setReference);
@@ -53,7 +53,7 @@ final class CodegenTypeGenerator extends AbstractTypeGenerator {
 
     @Override
     void addCodegenInformation(final GeneratedTypeBuilderBase<?> genType, final Module module) {
-        genType.setYangSourceDefinition(YangSourceDefinition.of(module));
+        YangSourceDefinition.of(module).ifPresent(genType::setYangSourceDefinition);
         TypeComments.description(module).ifPresent(genType::addComment);
         module.getDescription().ifPresent(genType::setDescription);
         module.getReference().ifPresent(genType::setReference);
@@ -64,7 +64,7 @@ final class CodegenTypeGenerator extends AbstractTypeGenerator {
             final String description, final Set<?  extends SchemaNode> nodes) {
         interfaceBuilder.addComment(TypeComments.javadoc("Interface for implementing the following YANG " + description
             + " defined in module <b>" + module.getName() + "</b>").get());
-        interfaceBuilder.setYangSourceDefinition(YangSourceDefinition.of(module, nodes));
+        YangSourceDefinition.of(module, nodes).ifPresent(interfaceBuilder::setYangSourceDefinition);
     }
 
     @Override
index 14f339bb725c961725bb035d246aa93f6d3e5a87..d5cd55fc37a8b82000efb73099994551e10e3ab1 100644 (file)
             <groupId>org.opendaylight.mdsal</groupId>
             <artifactId>mdsal-binding-generator-util</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-model-export</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.eclipse.xtend</groupId>
             <artifactId>org.eclipse.xtend.lib</artifactId>
             </exclusions>
         </dependency>
 
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>org.mockito</groupId>
             <artifactId>mockito-core</artifactId>
index ba43a0abde10289668164abc2e99b3209e4b7b7f..e578eced60842d162a98ca28813641b400ba36bc 100644 (file)
@@ -28,11 +28,15 @@ import org.opendaylight.mdsal.binding.model.util.Types
 import org.opendaylight.yangtools.yang.binding.CodeHelpers
 import org.opendaylight.yangtools.yang.common.QName
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
-import org.opendaylight.yangtools.yang.model.api.DocumentedNode
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition
 import org.opendaylight.yangtools.yang.model.api.RpcDefinition
 import org.opendaylight.yangtools.yang.model.api.SchemaNode
+import org.opendaylight.yangtools.yang.model.api.YangStmtMapping
+import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement
+import org.opendaylight.yangtools.yang.model.api.stmt.ModuleEffectiveStatement
+import org.opendaylight.yangtools.yang.model.export.DeclaredStatementFormatter
 
 abstract class BaseTemplate extends JavaFileTemplate {
     private static final char NEW_LINE = '\n'
@@ -42,6 +46,12 @@ abstract class BaseTemplate extends JavaFileTemplate {
     private static val SPACES_PATTERN = Pattern.compile(" +")
     private static val NL_SPLITTER = Splitter.on(NL_MATCHER)
     private static val TAIL_COMMENT_PATTERN = Pattern.compile("*/", Pattern.LITERAL);
+    private static val YANG_FORMATTER = DeclaredStatementFormatter.builder()
+        .addIgnoredStatement(YangStmtMapping.CONTACT)
+        .addIgnoredStatement(YangStmtMapping.DESCRIPTION)
+        .addIgnoredStatement(YangStmtMapping.REFERENCE)
+        .addIgnoredStatement(YangStmtMapping.ORGANIZATION)
+        .build();
 
     new(GeneratedType type) {
         super(type)
@@ -224,19 +234,19 @@ abstract class BaseTemplate extends JavaFileTemplate {
             val def = optDef.get
             sb.append(NEW_LINE)
 
-               if (def instanceof Single) {
+            if (def instanceof Single) {
                 val node = def.node
                 sb.append("<p>\n")
                 .append("This class represents the following YANG schema fragment defined in module <b>")
-                .append(def.module.name).append("</b>\n")
+                .append(def.module.argument).append("</b>\n")
                 .append("<pre>\n")
-                .append(encodeAngleBrackets(encodeJavadocSymbols(YangTemplate.generateYangSnippet(node))))
-                .append("</pre>")
+                appendYangSnippet(sb, def.module, (node as EffectiveStatement<?, ?>).declared)
+                sb.append("</pre>")
 
                 if (node instanceof SchemaNode) {
                     sb.append("The schema path to identify an instance is\n")
                     .append("<i>")
-                    .append(formatSchemaPath(def.module.name, node.path.pathFromRoot))
+                    .append(formatSchemaPath(def.module.argument, node.path.pathFromRoot))
                     .append("</i>\n")
 
                     if (hasBuilderClass(node)) {
@@ -254,16 +264,23 @@ abstract class BaseTemplate extends JavaFileTemplate {
                         }
                     }
                 }
-               } else if (def instanceof Multiple) {
+            } else if (def instanceof Multiple) {
                 sb.append("<pre>\n")
-                for (DocumentedNode schemaNode : def.nodes) {
-                    sb.append(encodeAngleBrackets(encodeJavadocSymbols(YangTemplate.generateYangSnippet(schemaNode))))
+                for (SchemaNode node : def.nodes) {
+                    appendYangSnippet(sb, def.module, (node as EffectiveStatement<?, ?>).declared)
                 }
                 sb.append("</pre>\n")
             }
         }
     }
 
+    def private static void appendYangSnippet(StringBuilder sb, ModuleEffectiveStatement module,
+            DeclaredStatement<?> stmt) {
+        for (String str : YANG_FORMATTER.toYangTextSnippet(module, stmt)) {
+            sb.append(encodeAngleBrackets(encodeJavadocSymbols(str)))
+        }
+    }
+
     def private static boolean hasBuilderClass(SchemaNode schemaNode) {
         return schemaNode instanceof ContainerSchemaNode || schemaNode instanceof ListSchemaNode
                 || schemaNode instanceof RpcDefinition || schemaNode instanceof NotificationDefinition;
diff --git a/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/YangTemplate.xtend b/binding/mdsal-binding-java-api-generator/src/main/java/org/opendaylight/mdsal/binding/java/api/generator/YangTemplate.xtend
deleted file mode 100644 (file)
index e38544e..0000000
+++ /dev/null
@@ -1,698 +0,0 @@
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.mdsal.binding.java.api.generator
-
-import java.util.Collection
-import java.util.List
-import java.util.Map
-import java.util.Set
-import org.opendaylight.mdsal.binding.model.util.FormattingUtils
-import org.opendaylight.yangtools.yang.common.Revision
-import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode
-import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode
-import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode
-import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
-import org.opendaylight.yangtools.yang.model.api.Deviation
-import org.opendaylight.yangtools.yang.model.api.DocumentedNode
-import org.opendaylight.yangtools.yang.model.api.ExtensionDefinition
-import org.opendaylight.yangtools.yang.model.api.FeatureDefinition
-import org.opendaylight.yangtools.yang.model.api.GroupingDefinition
-import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode
-import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
-import org.opendaylight.yangtools.yang.model.api.Module
-import org.opendaylight.yangtools.yang.model.api.ModuleImport
-import org.opendaylight.yangtools.yang.model.api.NotificationDefinition
-import org.opendaylight.yangtools.yang.model.api.RpcDefinition
-import org.opendaylight.yangtools.yang.model.api.SchemaNode
-import org.opendaylight.yangtools.yang.model.api.SchemaPath
-import org.opendaylight.yangtools.yang.model.api.Status
-import org.opendaylight.yangtools.yang.model.api.TypeDefinition
-import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode
-import org.opendaylight.yangtools.yang.model.api.UsesNode
-import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition
-import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition.EnumPair
-
-final class YangTemplate {
-
-    private static val String SKIP_PROPERTY_NAME = "mdsal.skip.verbose"
-
-    private static val SKIP = Boolean.getBoolean(SKIP_PROPERTY_NAME)
-
-    private static val SKIPPED_EMPTY = '''(Empty due to «SKIP_PROPERTY_NAME» property = true)'''
-
-    def static String generateYangSnippet(Module module) {
-        if (SKIP)
-            return SKIPPED_EMPTY
-        '''
-            module «module.name» {
-                yang-version «module.yangVersion»;
-                namespace "«module.QNameModule.namespace.toString»";
-                prefix "«module.prefix»";
-
-                «IF !module.imports.nullOrEmpty»
-                «writeModuleImports(module.imports)»
-                «ENDIF»
-                «IF module.revision.present»
-                «writeRevision(module.revision.get, module.description.orElse(null))»
-                «ENDIF»
-                «IF !module.childNodes.nullOrEmpty»
-
-                «writeDataSchemaNodes(module.childNodes)»
-                «ENDIF»
-                «IF !module.groupings.nullOrEmpty»
-
-                «writeGroupingDefs(module.groupings)»
-                «ENDIF»
-                «IF !module.augmentations.nullOrEmpty»
-
-                «writeAugments(module.augmentations)»
-                «ENDIF»
-                «IF !module.deviations.nullOrEmpty»
-
-                «writeDeviations(module.deviations)»
-                «ENDIF»
-                «IF !module.extensionSchemaNodes.nullOrEmpty»
-
-                «writeExtensions(module.extensionSchemaNodes)»
-                «ENDIF»
-                «IF !module.features.nullOrEmpty»
-
-                «writeFeatures(module.features)»
-                «ENDIF»
-                «IF !module.identities.nullOrEmpty»
-
-                «writeIdentities(module.identities)»
-                «ENDIF»
-                «IF !module.notifications.nullOrEmpty»
-
-                «writeNotifications(module.notifications)»
-                «ENDIF»
-                «IF !module.rpcs.nullOrEmpty»
-
-                «writeRPCs(module.rpcs)»
-                «ENDIF»
-                «IF !module.unknownSchemaNodes.nullOrEmpty»
-
-                «writeUnknownSchemaNodes(module.unknownSchemaNodes)»
-                «ENDIF»
-                «IF !module.uses.nullOrEmpty»
-
-                «writeUsesNodes(module.uses)»
-                «ENDIF»
-            }
-        '''
-    }
-
-    def static String generateYangSnippet(DocumentedNode schemaNode) {
-        if (schemaNode === null)
-            return ''
-        if (schemaNode instanceof Module)
-            return generateYangSnippet(schemaNode)
-        if (SKIP)
-            return SKIPPED_EMPTY
-        '''
-            «IF schemaNode instanceof DataSchemaNode»
-            «writeDataSchemaNode(schemaNode)»
-            «ENDIF»
-            «IF schemaNode instanceof EnumTypeDefinition.EnumPair»
-            «writeEnumPair(schemaNode)»
-            «ENDIF»
-            «IF schemaNode instanceof ExtensionDefinition»
-            «writeExtension(schemaNode)»
-            «ENDIF»
-            «IF schemaNode instanceof FeatureDefinition»
-            «writeFeature(schemaNode)»
-            «ENDIF»
-            «IF schemaNode instanceof GroupingDefinition»
-            «writeGroupingDef(schemaNode)»
-            «ENDIF»
-            «IF schemaNode instanceof IdentitySchemaNode»
-            «writeIdentity(schemaNode)»
-            «ENDIF»
-            «IF schemaNode instanceof NotificationDefinition»
-            «writeNotification(schemaNode)»
-            «ENDIF»
-            «IF schemaNode instanceof RpcDefinition»
-            «writeRPC(schemaNode)»
-            «ENDIF»
-            «IF schemaNode instanceof TypeDefinition<?>»
-            «writeTypeDefinition(schemaNode)»
-            «ENDIF»
-            «IF schemaNode instanceof UnknownSchemaNode»
-            «writeUnknownSchemaNode(schemaNode)»
-            «ENDIF»
-        '''
-    }
-
-    def private static writeEnumPair(EnumPair pair) {
-        '''
-            enum «pair.name» {
-                value «pair.value»;
-            }
-        '''
-    }
-
-    def private static String writeModuleImports(Set<ModuleImport> moduleImports) {
-        if (moduleImports.nullOrEmpty)
-            return ''
-
-        '''
-            «FOR moduleImport : moduleImports SEPARATOR "\n"»
-                «IF moduleImport !== null && !moduleImport.moduleName.nullOrEmpty»
-                import «moduleImport.moduleName» { prefix "«moduleImport.prefix»"; }
-                «ENDIF»
-            «ENDFOR»
-        '''
-    }
-
-    def private static writeRevision(Revision moduleRevision, String moduleDescription) {
-        val revisionIndent = 12
-
-        '''
-            revision «moduleRevision.toString» {
-                description "«FormattingUtils.formatToParagraph(moduleDescription, revisionIndent)»";
-            }
-        '''
-    }
-
-    def private static writeRPCs(Set<RpcDefinition> rpcDefs) {
-        '''
-            «FOR rpc : rpcDefs»
-                «IF rpc !== null»
-                «writeRPC(rpc)»
-                «ENDIF»
-            «ENDFOR»
-        '''
-    }
-
-    def private static writeRPC(RpcDefinition rpc) {
-        var boolean isStatusDeprecated = rpc.status == Status::DEPRECATED
-        '''
-            rpc «rpc.QName.localName» {
-                «IF rpc.description.present»
-                    "«rpc.description.get»";
-                «ENDIF»
-                «IF !rpc.groupings.nullOrEmpty»
-                    «writeGroupingDefs(rpc.groupings)»
-                «ENDIF»
-                «IF rpc.input !== null»
-                    «writeRpcInput(rpc.input)»
-                «ENDIF»
-                «IF rpc.output !== null»
-                    «writeRpcOutput(rpc.output)»
-                «ENDIF»
-                «IF rpc.reference.present»
-                reference
-                    "«rpc.reference.get»";
-                «ENDIF»
-                «IF isStatusDeprecated»
-                status «rpc.status»;
-                «ENDIF»
-            }
-        '''
-    }
-
-    def private static writeRpcInput(ContainerSchemaNode input) {
-        if (input === null)
-            return ''
-
-        '''
-            input {
-                «IF !input.childNodes.nullOrEmpty»
-                «writeDataSchemaNodes(input.childNodes)»
-                «ENDIF»
-            }
-
-        '''
-    }
-
-    def private static writeRpcOutput(ContainerSchemaNode output) {
-        if (output === null)
-            return ''
-
-        '''
-            output {
-                «IF !output.childNodes.nullOrEmpty»
-                «writeDataSchemaNodes(output.childNodes)»
-                «ENDIF»
-            }
-        '''
-    }
-
-    def private static writeNotifications(Set<NotificationDefinition> notifications) {
-        '''
-            «FOR notification : notifications»
-                «IF notification !== null»
-                «writeNotification(notification)»
-                «ENDIF»
-            «ENDFOR»
-        '''
-    }
-
-    def private static writeNotification(NotificationDefinition notification) {
-        var boolean isStatusDeprecated = notification.status == Status::DEPRECATED
-        '''
-            notification «notification.QName.localName» {
-                «IF notification.description.present»
-                description
-                    "«notification.description.get»";
-                «ENDIF»
-                «IF !notification.childNodes.nullOrEmpty»
-                    «writeDataSchemaNodes(notification.childNodes)»
-                «ENDIF»
-                «IF !notification.availableAugmentations.nullOrEmpty»
-                    «writeAugments(notification.availableAugmentations)»
-                «ENDIF»
-                «IF !notification.groupings.nullOrEmpty»
-                    «writeGroupingDefs(notification.groupings)»
-                «ENDIF»
-                «IF !notification.uses.nullOrEmpty»
-                    «writeUsesNodes(notification.uses)»
-                «ENDIF»
-                «IF notification.reference.present»
-                reference
-                    "«notification.reference.get»";
-                «ENDIF»
-                «IF isStatusDeprecated»
-                status «notification.status»;
-                «ENDIF»
-            }
-        '''
-    }
-
-    def private static writeUnknownSchemaNodes(List<UnknownSchemaNode> unknownSchemaNodes) {
-        if (unknownSchemaNodes.nullOrEmpty)
-            return ''
-
-        '''
-            «FOR unknownSchemaNode : unknownSchemaNodes»
-                «writeUnknownSchemaNode(unknownSchemaNode)»
-            «ENDFOR»
-        '''
-    }
-
-    def private static writeUnknownSchemaNode(UnknownSchemaNode unknownSchemaNode) {
-        return ''
-    }
-
-    def private static writeUsesNodes(Set<UsesNode> usesNodes) {
-        if (usesNodes === null) {
-            return ''
-        }
-
-        '''
-            «FOR usesNode : usesNodes»
-                «IF usesNode !== null»
-                «writeUsesNode(usesNode)»
-                «ENDIF»
-            «ENDFOR»
-        '''
-    }
-
-    def private static writeUsesNode(UsesNode usesNode) {
-        val hasRefines = !usesNode.refines.empty
-
-        '''
-            uses «usesNode.groupingPath.pathFromRoot.head.localName»«IF !hasRefines»;«ELSE» {«ENDIF»
-            «IF hasRefines»
-                «writeRefines(usesNode.refines)»
-            }
-            «ENDIF»
-        '''
-    }
-
-    def private static writeRefines(Map<SchemaPath, SchemaNode> refines) {
-        '''
-            «FOR path : refines.keySet»
-            «val schemaNode = refines.get(path)»
-            «writeRefine(path, schemaNode)»
-            «ENDFOR»
-        '''
-    }
-
-    def private static writeRefine(SchemaPath path, SchemaNode schemaNode) {
-        '''
-            refine «path.pathFromRoot.last» {
-                «IF schemaNode instanceof DataSchemaNode»
-                «writeDataSchemaNode(schemaNode)»
-                «ENDIF»
-            }
-        '''
-    }
-
-    def private static writeTypeDefinition(TypeDefinition<?> typeDefinition) {
-        var boolean isStatusDeprecated = typeDefinition.status == Status::DEPRECATED
-        '''
-            type «typeDefinition.QName.localName»«IF !isStatusDeprecated»;«ELSE» {
-                status «typeDefinition.status»;
-            }
-            «ENDIF»
-        '''
-    }
-
-    def private static writeIdentities(Set<IdentitySchemaNode> identities) {
-        if (identities.nullOrEmpty)
-            return ''
-        '''
-            «FOR identity : identities»
-                «writeIdentity(identity)»
-            «ENDFOR»
-        '''
-    }
-
-    def private static writeIdentity(IdentitySchemaNode identity) {
-        if (identity === null)
-            return ''
-        '''
-            identity «identity.QName.localName» {
-                «FOR baseIdentity : identity.baseIdentities»
-                base "()«baseIdentity»";
-                «ENDFOR»
-                «IF identity.description.present»
-                description
-                    "«identity.description.get»";
-                «ENDIF»
-                «IF identity.reference.present»
-                reference
-                    "«identity.reference.get»";
-                «ENDIF»
-                «IF identity.status !== null»
-                status «identity.status»;
-                «ENDIF»
-            }
-        '''
-    }
-
-    def private static writeFeatures(Set<FeatureDefinition> features) {
-        '''
-            «FOR feature : features»
-                «IF feature !== null»
-                «writeFeature(feature)»
-                «ENDIF»
-            «ENDFOR»
-        '''
-    }
-
-    def private static writeFeature(FeatureDefinition featureDef) {
-        '''
-            feature «featureDef.QName.localName» {
-                «IF featureDef.description.present»
-                description
-                    "«featureDef.description.get»";
-                «ENDIF»
-                «IF featureDef.reference.present»
-                reference
-                    "«featureDef.reference.get»";
-                «ENDIF»
-                «IF featureDef.status !== null»
-                status «featureDef.status»;
-                «ENDIF»
-            }
-        '''
-    }
-
-    def private static writeExtensions(List<ExtensionDefinition> extensions) {
-        '''
-            «FOR anExtension : extensions»
-                «IF anExtension !== null»
-                «writeExtension(anExtension)»
-                «ENDIF»
-            «ENDFOR»
-        '''
-    }
-
-    def private static writeExtension(ExtensionDefinition extensionDef) {
-        '''
-            extension «extensionDef.QName.localName» {
-                «IF extensionDef.description.present»
-                description
-                    "«extensionDef.description.get»";
-                «ENDIF»
-                «IF !extensionDef.argument.nullOrEmpty»
-                argument "«extensionDef.argument»";
-                «ENDIF»
-                «IF extensionDef.reference.present»
-                reference
-                    "«extensionDef.reference.get»";
-                «ENDIF»
-                «IF extensionDef.status !== null»
-                status «extensionDef.status»;
-                «ENDIF»
-            }
-        '''
-    }
-
-    def private static writeDeviations(Set<Deviation> deviations) {
-        '''
-            «FOR deviation : deviations»
-                «IF deviation !== null»
-                «writeDeviation(deviation)»
-                «ENDIF»
-            «ENDFOR»
-        '''
-    }
-
-    def private static writeDeviation(Deviation deviation) {
-        '''
-            deviation «deviation.targetPath» {
-                «IF deviation.reference.present»
-                    reference
-                        "«deviation.reference.get»";
-                «ENDIF»
-                «FOR dev : deviation.deviates»
-                    «IF dev !== null && dev.deviateType !== null»
-                        deviation «dev.deviateType.name»;
-                    «ENDIF»
-                «ENDFOR»
-            }
-        '''
-    }
-
-    def private static writeAugments(Set<AugmentationSchemaNode> augments) {
-        '''
-            «FOR augment : augments»
-                «IF augment !== null»
-                «writeAugment(augment)»
-                «ENDIF»
-            «ENDFOR»
-        '''
-    }
-
-    def private static writeDataSchemaNodes(Collection<DataSchemaNode> dataSchemaNodes) {
-        '''
-            «FOR schemaNode : dataSchemaNodes»
-                «writeDataSchemaNode(schemaNode)»
-            «ENDFOR»
-        '''
-    }
-
-    def private static CharSequence writeGroupingDefs(Set<GroupingDefinition> groupingDefs) {
-        '''
-            «FOR groupingDef : groupingDefs»
-                «IF groupingDef !== null»
-                «writeGroupingDef(groupingDef)»
-                «ENDIF»
-            «ENDFOR»
-        '''
-    }
-
-    def private static writeAugment(AugmentationSchemaNode augment) {
-        '''
-            augment «FormattingUtils.formatToAugmentPath(augment.targetPath.pathFromRoot)» {
-                «IF augment.whenCondition !== null && !augment.whenCondition.toString.nullOrEmpty»
-                when "«augment.whenCondition.toString»";
-                «ENDIF»
-                «IF augment.description.present»
-                description
-                    "«augment.description.get»";
-                «ENDIF»
-                «IF augment.reference.present»
-                reference
-                    "«augment.reference.get»";
-                «ENDIF»
-                «IF augment.status !== null»
-                status «augment.status»;
-                «ENDIF»
-                «IF !augment.childNodes.nullOrEmpty»
-                «writeDataSchemaNodes(augment.childNodes)»
-                «ENDIF»
-                «IF !augment.uses.nullOrEmpty»
-                «writeUsesNodes(augment.uses)»
-                «ENDIF»
-            }
-        '''
-    }
-
-    def private static writeGroupingDef(GroupingDefinition groupingDef) {
-        var boolean isStatusDeprecated = groupingDef.status == Status::DEPRECATED
-        '''
-            grouping «groupingDef.QName.localName» {
-                «IF !groupingDef.groupings.nullOrEmpty»
-                    «writeGroupingDefs(groupingDef.groupings)»
-                «ENDIF»
-                «IF !groupingDef.childNodes.nullOrEmpty»
-                    «writeDataSchemaNodes(groupingDef.childNodes)»
-                «ENDIF»
-                «IF isStatusDeprecated»
-                    status «groupingDef.status»;
-                «ENDIF»
-                «IF !groupingDef.unknownSchemaNodes.nullOrEmpty»
-                    «writeUnknownSchemaNodes(groupingDef.unknownSchemaNodes)»
-                «ENDIF»
-            }
-        '''
-    }
-
-    def private static writeContSchemaNode(ContainerSchemaNode contSchemaNode) {
-        var boolean isStatusDeprecated = contSchemaNode.status == Status::DEPRECATED
-        '''
-            container «contSchemaNode.getQName.localName» {
-                «IF !contSchemaNode.childNodes.nullOrEmpty»
-                «writeDataSchemaNodes(contSchemaNode.childNodes)»
-                «ENDIF»
-                «IF !contSchemaNode.availableAugmentations.nullOrEmpty»
-                «writeAugments(contSchemaNode.availableAugmentations)»
-                «ENDIF»
-                «IF !contSchemaNode.groupings.nullOrEmpty»
-                «writeGroupingDefs(contSchemaNode.groupings)»
-                «ENDIF»
-                «IF !contSchemaNode.uses.nullOrEmpty»
-                «writeUsesNodes(contSchemaNode.uses)»
-                «ENDIF»
-                «IF isStatusDeprecated»
-                status «contSchemaNode.status»;
-                «ENDIF»
-                «IF !contSchemaNode.unknownSchemaNodes.nullOrEmpty»
-                «writeUnknownSchemaNodes(contSchemaNode.unknownSchemaNodes)»
-                «ENDIF»
-            }
-        '''
-    }
-
-    def private static writeAnyXmlSchemaNode(AnyXmlSchemaNode anyXmlSchemaNode) {
-        var boolean isStatusDeprecated = anyXmlSchemaNode.status == Status::DEPRECATED
-        '''
-            anyxml «anyXmlSchemaNode.getQName.localName»«IF !isStatusDeprecated»;«ELSE» {
-                status «anyXmlSchemaNode.status»;
-            }
-            «ENDIF»
-        '''
-    }
-
-    def private static writeLeafSchemaNode(LeafSchemaNode leafSchemaNode) {
-        var boolean isStatusDeprecated = leafSchemaNode.status == Status::DEPRECATED
-        '''
-            leaf «leafSchemaNode.getQName.localName» {
-                type «leafSchemaNode.type.getQName.localName»;
-                «IF isStatusDeprecated»
-                    status «leafSchemaNode.status»;
-                «ENDIF»
-            }
-        '''
-    }
-
-    def private static writeLeafListSchemaNode(LeafListSchemaNode leafListSchemaNode) {
-        var boolean isStatusDeprecated = leafListSchemaNode.status == Status::DEPRECATED
-        '''
-            leaf-list «leafListSchemaNode.getQName.localName» {
-                type «leafListSchemaNode.type.getQName.localName»;
-                «IF isStatusDeprecated»
-                    status «leafListSchemaNode.status»;
-                «ENDIF»
-            }
-        '''
-    }
-
-    def private static writeCaseSchemaNode(CaseSchemaNode choiceCaseNode) {
-        var boolean isStatusDeprecated = choiceCaseNode.status == Status::DEPRECATED
-        '''
-            case «choiceCaseNode.getQName.localName» {
-                «FOR childNode : choiceCaseNode.childNodes»
-                    «writeDataSchemaNode(childNode)»
-                «ENDFOR»
-                «IF isStatusDeprecated»
-                    status «choiceCaseNode.status»;
-                «ENDIF»
-            }
-        '''
-    }
-
-    def private static writeChoiceNode(ChoiceSchemaNode choiceNode) {
-        var boolean isStatusDeprecated = choiceNode.status == Status::DEPRECATED
-        '''
-            choice «choiceNode.getQName.localName» {
-                «FOR child : choiceNode.cases.values»
-                    «writeDataSchemaNode(child)»
-                «ENDFOR»
-                «IF isStatusDeprecated»
-                    status «choiceNode.status»;
-                «ENDIF»
-            }
-        '''
-    }
-
-    def private static writeListSchemaNode(ListSchemaNode listSchemaNode) {
-        var boolean isStatusDeprecated = listSchemaNode.status == Status::DEPRECATED
-
-        '''
-            list «listSchemaNode.getQName.localName» {
-                «IF !listSchemaNode.keyDefinition.empty»
-                    key «FOR listKey : listSchemaNode.keyDefinition SEPARATOR " "»"«listKey.localName»"«ENDFOR»;
-                «ENDIF»
-                «IF !listSchemaNode.childNodes.nullOrEmpty»
-                    «writeDataSchemaNodes(listSchemaNode.childNodes)»
-                «ENDIF»
-                «IF !listSchemaNode.availableAugmentations.nullOrEmpty»
-                    «writeAugments(listSchemaNode.availableAugmentations)»
-                «ENDIF»
-                «IF !listSchemaNode.groupings.nullOrEmpty»
-                    «writeGroupingDefs(listSchemaNode.groupings)»
-                «ENDIF»
-                «IF !listSchemaNode.uses.nullOrEmpty»
-                    «writeUsesNodes(listSchemaNode.uses)»
-                «ENDIF»
-                «IF isStatusDeprecated»
-                    status «listSchemaNode.status»;
-                «ENDIF»
-                «IF !listSchemaNode.unknownSchemaNodes.nullOrEmpty»
-                    «writeUnknownSchemaNodes(listSchemaNode.unknownSchemaNodes)»
-                «ENDIF»
-            }
-        '''
-    }
-
-    def private static CharSequence writeDataSchemaNode(DataSchemaNode child) {
-        '''
-            «IF child instanceof ContainerSchemaNode»
-                «writeContSchemaNode(child)»
-            «ENDIF»
-            «IF child instanceof AnyXmlSchemaNode»
-                «writeAnyXmlSchemaNode(child)»
-            «ENDIF»
-            «IF child instanceof LeafSchemaNode»
-                «writeLeafSchemaNode(child)»
-            «ENDIF»
-            «IF child instanceof LeafListSchemaNode»
-                «writeLeafListSchemaNode(child)»
-            «ENDIF»
-            «IF child instanceof CaseSchemaNode»
-                «writeCaseSchemaNode(child)»
-            «ENDIF»
-            «IF child instanceof ChoiceSchemaNode»
-                «writeChoiceNode(child)»
-            «ENDIF»
-            «IF child instanceof ListSchemaNode»
-                «writeListSchemaNode(child)»
-            «ENDIF»
-        '''
-    }
-}