Switch to Objects.requireNonNull
[mdsal.git] / binding2 / mdsal-binding2-generator-impl / src / main / java / org / opendaylight / mdsal / binding / javav2 / generator / impl / GenHelperUtil.java
old mode 100644 (file)
new mode 100755 (executable)
index 51cc818..9dc44c1
@@ -9,10 +9,10 @@
 package org.opendaylight.mdsal.binding.javav2.generator.impl;
 
 import static com.google.common.base.Preconditions.checkArgument;
 package org.opendaylight.mdsal.binding.javav2.generator.impl;
 
 import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
 import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.addTOToTypeBuilder;
 import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.annotateDeprecatedIfNecessary;
 import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.constructGetter;
 import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.addTOToTypeBuilder;
 import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.annotateDeprecatedIfNecessary;
 import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.constructGetter;
-import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.createDescription;
 import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.createReturnTypeForUnion;
 import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.getAugmentIdentifier;
 import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.isInnerType;
 import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.createReturnTypeForUnion;
 import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.getAugmentIdentifier;
 import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.isInnerType;
@@ -28,18 +28,20 @@ import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingTypes.
 import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingTypes.NOTIFICATION;
 import static org.opendaylight.mdsal.binding.javav2.generator.util.Types.parameterizedTypeFor;
 import static org.opendaylight.mdsal.binding.javav2.generator.util.Types.wildcardTypeFor;
 import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingTypes.NOTIFICATION;
 import static org.opendaylight.mdsal.binding.javav2.generator.util.Types.parameterizedTypeFor;
 import static org.opendaylight.mdsal.binding.javav2.generator.util.Types.wildcardTypeFor;
-import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNode;
+import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.resolveRegExpressions;
 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findParentModule;
 
 import com.google.common.annotations.Beta;
 import com.google.common.base.Preconditions;
 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findParentModule;
 
 import com.google.common.annotations.Beta;
 import com.google.common.base.Preconditions;
-import com.google.common.collect.Iterables;
+
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
+import javax.annotation.Nullable;
+
 import org.opendaylight.mdsal.binding.javav2.generator.context.ModuleContext;
 import org.opendaylight.mdsal.binding.javav2.generator.spi.TypeProvider;
 import org.opendaylight.mdsal.binding.javav2.generator.util.BindingGeneratorUtil;
 import org.opendaylight.mdsal.binding.javav2.generator.context.ModuleContext;
 import org.opendaylight.mdsal.binding.javav2.generator.spi.TypeProvider;
 import org.opendaylight.mdsal.binding.javav2.generator.util.BindingGeneratorUtil;
@@ -47,10 +49,11 @@ import org.opendaylight.mdsal.binding.javav2.generator.util.BindingTypes;
 import org.opendaylight.mdsal.binding.javav2.generator.util.JavaIdentifier;
 import org.opendaylight.mdsal.binding.javav2.generator.util.JavaIdentifierNormalizer;
 import org.opendaylight.mdsal.binding.javav2.generator.util.ReferencedTypeImpl;
 import org.opendaylight.mdsal.binding.javav2.generator.util.JavaIdentifier;
 import org.opendaylight.mdsal.binding.javav2.generator.util.JavaIdentifierNormalizer;
 import org.opendaylight.mdsal.binding.javav2.generator.util.ReferencedTypeImpl;
+import org.opendaylight.mdsal.binding.javav2.generator.util.TypeComments;
 import org.opendaylight.mdsal.binding.javav2.generator.util.Types;
 import org.opendaylight.mdsal.binding.javav2.generator.util.generated.type.builder.GeneratedPropertyBuilderImpl;
 import org.opendaylight.mdsal.binding.javav2.generator.util.Types;
 import org.opendaylight.mdsal.binding.javav2.generator.util.generated.type.builder.GeneratedPropertyBuilderImpl;
-import org.opendaylight.mdsal.binding.javav2.generator.util.generated.type.builder.GeneratedTOBuilderImpl;
 import org.opendaylight.mdsal.binding.javav2.generator.util.generated.type.builder.GeneratedTypeBuilderImpl;
 import org.opendaylight.mdsal.binding.javav2.generator.util.generated.type.builder.GeneratedTypeBuilderImpl;
+import org.opendaylight.mdsal.binding.javav2.generator.yang.types.BaseYangTypes;
 import org.opendaylight.mdsal.binding.javav2.generator.yang.types.GroupingDefinitionDependencySort;
 import org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeProviderImpl;
 import org.opendaylight.mdsal.binding.javav2.model.api.AccessModifier;
 import org.opendaylight.mdsal.binding.javav2.generator.yang.types.GroupingDefinitionDependencySort;
 import org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeProviderImpl;
 import org.opendaylight.mdsal.binding.javav2.model.api.AccessModifier;
@@ -58,6 +61,7 @@ import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedType;
 import org.opendaylight.mdsal.binding.javav2.model.api.ParameterizedType;
 import org.opendaylight.mdsal.binding.javav2.model.api.Restrictions;
 import org.opendaylight.mdsal.binding.javav2.model.api.Type;
 import org.opendaylight.mdsal.binding.javav2.model.api.ParameterizedType;
 import org.opendaylight.mdsal.binding.javav2.model.api.Restrictions;
 import org.opendaylight.mdsal.binding.javav2.model.api.Type;
+import org.opendaylight.mdsal.binding.javav2.model.api.YangSourceDefinition;
 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.EnumBuilder;
 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedPropertyBuilder;
 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedTOBuilder;
 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.EnumBuilder;
 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedPropertyBuilder;
 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedTOBuilder;
@@ -70,8 +74,8 @@ import org.opendaylight.mdsal.binding.javav2.util.BindingMapping;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.AnyDataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.AnyDataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
-import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+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.DataNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
@@ -92,6 +96,7 @@ import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.UsesNode;
 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.UsesNode;
 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
 import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
 import org.opendaylight.yangtools.yang.model.util.SchemaNodeUtils;
 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
 import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
 import org.opendaylight.yangtools.yang.model.util.SchemaNodeUtils;
@@ -109,43 +114,43 @@ final class GenHelperUtil {
     /**
      * Create GeneratedTypeBuilder object from module argument.
      *
     /**
      * Create GeneratedTypeBuilder object from module argument.
      *
-     * @param module
-     *            Module object from which builder will be created
-     * @param genCtx generated context
+     * @param module               Module object from which builder will be created
+     * @param genCtx               generated context
      * @param verboseClassComments verbosity switch
      * @param verboseClassComments verbosity switch
-     *
      * @return <code>GeneratedTypeBuilder</code> which is internal
      * @return <code>GeneratedTypeBuilder</code> which is internal
-     *         representation of the module
-     * @throws IllegalArgumentException
-     *             if module is null
+     *      representation of the module
+     * @throws IllegalArgumentException if module is null
      */
      */
-    static GeneratedTypeBuilder moduleToDataType(final Module module, final Map<Module, ModuleContext> genCtx, final boolean verboseClassComments) {
+    static GeneratedTypeBuilder moduleToDataType(final Module module, final Map<Module, ModuleContext> genCtx,
+        final boolean verboseClassComments) {
         Preconditions.checkArgument(module != null, "Module reference cannot be NULL.");
 
         final GeneratedTypeBuilder moduleDataTypeBuilder = moduleTypeBuilder(module, "Data", verboseClassComments,
                 genCtx.get(module));
         addImplementedInterfaceFromUses(module, moduleDataTypeBuilder, genCtx);
         moduleDataTypeBuilder.addImplementsType(BindingTypes.TREE_ROOT);
         Preconditions.checkArgument(module != null, "Module reference cannot be NULL.");
 
         final GeneratedTypeBuilder moduleDataTypeBuilder = moduleTypeBuilder(module, "Data", verboseClassComments,
                 genCtx.get(module));
         addImplementedInterfaceFromUses(module, moduleDataTypeBuilder, genCtx);
         moduleDataTypeBuilder.addImplementsType(BindingTypes.TREE_ROOT);
-        moduleDataTypeBuilder.addComment(module.getDescription());
-        moduleDataTypeBuilder.setDescription(createDescription(module, verboseClassComments));
-        moduleDataTypeBuilder.setReference(module.getReference());
+
+        if (verboseClassComments) {
+            YangSourceDefinition.of(module).ifPresent(moduleDataTypeBuilder::setYangSourceDefinition);
+            TypeComments.description(module).ifPresent(moduleDataTypeBuilder::addComment);
+            module.getDescription().ifPresent(moduleDataTypeBuilder::setDescription);
+            module.getReference().ifPresent(moduleDataTypeBuilder::setReference);
+        }
+
         return moduleDataTypeBuilder;
     }
 
     /**
      * Generates type builder for <code>module</code>.
      *
         return moduleDataTypeBuilder;
     }
 
     /**
      * Generates type builder for <code>module</code>.
      *
-     * @param module
-     *            Module which is source of package name for generated type
-     *            builder
-     * @param postfix
-     *            string which is added to the module class name representation
-     *            as suffix
+     * @param module               Module which is source of package name for generated type
+     *                             builder
+     * @param postfix              string which is added to the module class name representation
+     *                             as suffix
      * @param verboseClassComments verbosity switch
      * @return instance of GeneratedTypeBuilder which represents
      * @param verboseClassComments verbosity switch
      * @return instance of GeneratedTypeBuilder which represents
-     *         <code>module</code>.
-     * @throws IllegalArgumentException
-     *             if <code>module</code> is null
+     * <code>module</code>.
+     * @throws IllegalArgumentException if <code>module</code> is null
      */
     static GeneratedTypeBuilder moduleTypeBuilder(final Module module, final String postfix, final boolean
             verboseClassComments, final ModuleContext context) {
      */
     static GeneratedTypeBuilder moduleTypeBuilder(final Module module, final String postfix, final boolean
             verboseClassComments, final ModuleContext context) {
@@ -155,8 +160,12 @@ final class GenHelperUtil {
         final String moduleName = new StringBuilder(module.getName()).append('_').append(postfix).toString();
 
         final GeneratedTypeBuilderImpl moduleBuilder = new GeneratedTypeBuilderImpl(packageName, moduleName, context);
         final String moduleName = new StringBuilder(module.getName()).append('_').append(postfix).toString();
 
         final GeneratedTypeBuilderImpl moduleBuilder = new GeneratedTypeBuilderImpl(packageName, moduleName, context);
-        moduleBuilder.setDescription(createDescription(module, verboseClassComments));
-        moduleBuilder.setReference(module.getReference());
+        if (verboseClassComments) {
+            YangSourceDefinition.of(module).ifPresent(moduleBuilder::setYangSourceDefinition);
+            TypeComments.description(module).ifPresent(moduleBuilder::addComment);
+            module.getDescription().ifPresent(moduleBuilder::setDescription);
+            module.getReference().ifPresent(moduleBuilder::setReference);
+        }
         moduleBuilder.setModuleName(moduleName);
         return moduleBuilder;
     }
         moduleBuilder.setModuleName(moduleName);
         return moduleBuilder;
     }
@@ -164,34 +173,34 @@ final class GenHelperUtil {
     /**
      * Adds the implemented types to type builder.
      *
     /**
      * Adds the implemented types to type builder.
      *
+     * <p>
      * The method passes through the list of <i>uses</i> in
      * {@code dataNodeContainer}. For every <i>use</i> is obtained corresponding
      * generated type from all groupings
      * allGroupings} which is added as <i>implements type</i> to
      * <code>builder</code>
      *
      * The method passes through the list of <i>uses</i> in
      * {@code dataNodeContainer}. For every <i>use</i> is obtained corresponding
      * generated type from all groupings
      * allGroupings} which is added as <i>implements type</i> to
      * <code>builder</code>
      *
-     * @param dataNodeContainer
-     *            element which contains the list of used YANG groupings
-     * @param builder
-     *            builder to which are added implemented types according to
-     *            <code>dataNodeContainer</code>
-     * @param genCtx generated context
+     * @param dataNodeContainer element which contains the list of used YANG groupings
+     * @param builder           builder to which are added implemented types according to
+     *                          <code>dataNodeContainer</code>
+     * @param genCtx            generated context
      * @return generated type builder with all implemented types
      */
     static GeneratedTypeBuilder addImplementedInterfaceFromUses(final DataNodeContainer dataNodeContainer,
      * @return generated type builder with all implemented types
      */
     static GeneratedTypeBuilder addImplementedInterfaceFromUses(final DataNodeContainer dataNodeContainer,
-                          final GeneratedTypeBuilder builder, final Map<Module, ModuleContext> genCtx) {
+                                                                final GeneratedTypeBuilder builder, final Map<Module,
+            ModuleContext> genCtx) {
         for (final UsesNode usesNode : dataNodeContainer.getUses()) {
             final GeneratedType genType = findGroupingByPath(usesNode.getGroupingPath(), genCtx).toInstance();
             if (genType == null) {
                 throw new IllegalStateException("Grouping " + usesNode.getGroupingPath() + "is not resolved for "
         for (final UsesNode usesNode : dataNodeContainer.getUses()) {
             final GeneratedType genType = findGroupingByPath(usesNode.getGroupingPath(), genCtx).toInstance();
             if (genType == null) {
                 throw new IllegalStateException("Grouping " + usesNode.getGroupingPath() + "is not resolved for "
-                    + builder.getName());
+                        + builder.getName());
             }
             builder.addImplementsType(genType);
         }
         return builder;
     }
 
             }
             builder.addImplementsType(genType);
         }
         return builder;
     }
 
-     static GeneratedTypeBuilder findGroupingByPath(final SchemaPath path, final Map<Module, ModuleContext> genCtx) {
+    static GeneratedTypeBuilder findGroupingByPath(final SchemaPath path, final Map<Module, ModuleContext> genCtx) {
         for (final ModuleContext ctx : genCtx.values()) {
             final GeneratedTypeBuilder result = ctx.getGrouping(path);
             if (result != null) {
         for (final ModuleContext ctx : genCtx.values()) {
             final GeneratedTypeBuilder result = ctx.getGrouping(path);
             if (result != null) {
@@ -199,11 +208,11 @@ final class GenHelperUtil {
             }
         }
         return null;
             }
         }
         return null;
-     }
+    }
 
 
-    static GeneratedTOBuilder findIdentityByQname(final QName qname, final Map<Module, ModuleContext> genCtx) {
+    static GeneratedTypeBuilder findIdentityByQname(final QName qname, final Map<Module, ModuleContext> genCtx) {
         for (final ModuleContext ctx : genCtx.values()) {
         for (final ModuleContext ctx : genCtx.values()) {
-            final GeneratedTOBuilder result = ctx.getIdentities().get(qname);
+            final GeneratedTypeBuilder result = ctx.getIdentities().get(qname);
             if (result != null) {
                 return result;
             }
             if (result != null) {
                 return result;
             }
@@ -215,33 +224,34 @@ final class GenHelperUtil {
      * Adds the methods to <code>typeBuilder</code> which represent subnodes of
      * node for which <code>typeBuilder</code> was created.
      *
      * Adds the methods to <code>typeBuilder</code> which represent subnodes of
      * node for which <code>typeBuilder</code> was created.
      *
+     * <p>
      * The subnodes aren't mapped to the methods if they are part of grouping or
      * augment (in this case are already part of them).
      *
      * The subnodes aren't mapped to the methods if they are part of grouping or
      * augment (in this case are already part of them).
      *
-     * @param module
-     *            current module
-     * @param basePackageName
-     *            string contains the module package name
-     * @param parent
-     *            generated type builder which represents any node. The subnodes
-     *            of this node are added to the <code>typeBuilder</code> as
-     *            methods. The subnode can be of type leaf, leaf-list, list,
-     *            container, choice.
-     * @param childOf
-     *            parent type
-     * @param schemaNodes
-     *            set of data schema nodes which are the children of the node
-     *            for which <code>typeBuilder</code> was created
+     * @param module          current module
+     * @param basePackageName string contains the module package name
+     * @param parent          generated type builder which represents any node. The subnodes
+     *                        of this node are added to the <code>typeBuilder</code> as
+     *                        methods. The subnode can be of type leaf, leaf-list, list,
+     *                        container, choice.
+     * @param childOf         parent type
+     * @param schemaNodes     set of data schema nodes which are the children of the node
+     *      for which <code>typeBuilder</code> was created
      * @return generated type builder which is the same builder as input
      * @return generated type builder which is the same builder as input
-     *         parameter. The getter methods (representing child nodes) could be
-     *         added to it.
+     *      parameter. The getter methods (representing child nodes) could be
+     *      added to it.
      */
     static GeneratedTypeBuilder resolveDataSchemaNodes(final Module module, final String basePackageName,
      */
     static GeneratedTypeBuilder resolveDataSchemaNodes(final Module module, final String basePackageName,
-                          final GeneratedTypeBuilder parent, final GeneratedTypeBuilder childOf,
-                          final Iterable<DataSchemaNode> schemaNodes, final Map<Module, ModuleContext> genCtx,
-                          final SchemaContext schemaContext, final boolean verboseClassComments,
-                          final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders,
-                          final TypeProvider typeProvider, final BindingNamespaceType namespaceType) {
+                                                       final GeneratedTypeBuilder parent, final GeneratedTypeBuilder
+                                                               childOf,
+                                                       final Iterable<DataSchemaNode> schemaNodes, final Map<Module,
+            ModuleContext> genCtx,
+                                                       final SchemaContext schemaContext, final boolean
+                                                               verboseClassComments,
+                                                       final Map<String, Map<String, GeneratedTypeBuilder>>
+                                                               genTypeBuilders,
+                                                       final TypeProvider typeProvider, final BindingNamespaceType
+                                                               namespaceType) {
 
         if (schemaNodes != null && parent != null) {
             for (final DataSchemaNode schemaNode : schemaNodes) {
 
         if (schemaNodes != null && parent != null) {
             for (final DataSchemaNode schemaNode : schemaNodes) {
@@ -255,32 +265,24 @@ final class GenHelperUtil {
     }
 
     static boolean resolveDataSchemaNodesCheck(final Module module, final SchemaContext schemaContext,
     }
 
     static boolean resolveDataSchemaNodesCheck(final Module module, final SchemaContext schemaContext,
-            final DataSchemaNode schemaNode) {
+                                               final DataSchemaNode schemaNode) {
         if (!schemaNode.isAugmenting()) {
             return true;
         }
 
         final QName qname = schemaNode.getPath().getLastComponent();
         if (!schemaNode.isAugmenting()) {
             return true;
         }
 
         final QName qname = schemaNode.getPath().getLastComponent();
-        final Module originalModule = schemaContext.findModuleByNamespaceAndRevision(qname.getNamespace(),
-            qname.getRevision());
+        final Module originalModule = schemaContext.findModule(qname.getModule()).get();
         return module.equals(originalModule);
     }
 
         return module.equals(originalModule);
     }
 
-    static GeneratedTypeBuilder addDefaultInterfaceDefinition(final String basePackageName, final SchemaNode
-            schemaNode, final Module module, final Map<Module, ModuleContext> genCtx, final SchemaContext schemaContext,
-            final boolean verboseClassComments, final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders,
-            final TypeProvider typeProvider, final BindingNamespaceType namespaceType) {
-        return addDefaultInterfaceDefinition(basePackageName, schemaNode, null, module, genCtx, schemaContext,
-                verboseClassComments, genTypeBuilders, typeProvider , namespaceType);
-    }
-
-    private static QName createQNameFromSuperNode(final Module module, final Object node, final SchemaNode superChildNode) {
+    private static QName createQNameFromSuperNode(final Module module, final Object node, final SchemaNode
+            superChildNode) {
         QName childNodeQName = null;
         if (node instanceof Module) {
             childNodeQName = QName.create(((Module) node).getQNameModule(), superChildNode.getQName().getLocalName());
         } else if (node instanceof SchemaNode) {
             childNodeQName = QName.create(((SchemaNode) node).getQName(), superChildNode.getQName().getLocalName());
         QName childNodeQName = null;
         if (node instanceof Module) {
             childNodeQName = QName.create(((Module) node).getQNameModule(), superChildNode.getQName().getLocalName());
         } else if (node instanceof SchemaNode) {
             childNodeQName = QName.create(((SchemaNode) node).getQName(), superChildNode.getQName().getLocalName());
-        } else if (node instanceof AugmentationSchema) {
+        } else if (node instanceof AugmentationSchemaNode) {
             childNodeQName = QName.create(module.getQNameModule(), superChildNode.getQName().getLocalName());
         } else {
             throw new IllegalArgumentException("Not support node type:" + node);
             childNodeQName = QName.create(module.getQNameModule(), superChildNode.getQName().getLocalName());
         } else {
             throw new IllegalArgumentException("Not support node type:" + node);
@@ -290,44 +292,47 @@ final class GenHelperUtil {
     }
 
     private static void addUsesImplements(final SchemaNode superNode, final Module superModule,
     }
 
     private static void addUsesImplements(final SchemaNode superNode, final Module superModule,
-            final Object node, final Module module, final SchemaContext schemaContext,
-            final Map<Module, ModuleContext> genCtx, final BindingNamespaceType namespaceType) {
+                                          final Object node, final Module module, final SchemaContext schemaContext,
+                                          final Map<Module, ModuleContext> genCtx, final BindingNamespaceType
+                                                  namespaceType) {
         if (superNode instanceof DataNodeContainer) {
             for (DataSchemaNode superChildNode : ((DataNodeContainer) superNode).getChildNodes()) {
                 if (superChildNode instanceof DataNodeContainer || superChildNode instanceof ChoiceSchemaNode) {
                     final QName childQName = createQNameFromSuperNode(module, node, superChildNode);
                     DataSchemaNode childNode = ((DataNodeContainer) node).getDataChildByName(childQName);
         if (superNode instanceof DataNodeContainer) {
             for (DataSchemaNode superChildNode : ((DataNodeContainer) superNode).getChildNodes()) {
                 if (superChildNode instanceof DataNodeContainer || superChildNode instanceof ChoiceSchemaNode) {
                     final QName childQName = createQNameFromSuperNode(module, node, superChildNode);
                     DataSchemaNode childNode = ((DataNodeContainer) node).getDataChildByName(childQName);
-                    Preconditions.checkNotNull(childNode, "%s->%s", node, childQName);
+                    requireNonNull(childNode, () -> node + "->" + childQName);
 
                     final GeneratedTypeBuilder type = genCtx.get(module).getChildNode(childNode.getPath());
 
                     final GeneratedTypeBuilder type = genCtx.get(module).getChildNode(childNode.getPath());
-                    final GeneratedTypeBuilder superType = genCtx.get(superModule).getChildNode(superChildNode.getPath());
+                    final GeneratedTypeBuilder superType = genCtx.get(superModule).getChildNode(superChildNode
+                            .getPath());
 
 
-                    Preconditions.checkNotNull(type, "%s->%s", module, childNode.getPath());
-                    Preconditions.checkNotNull(superType, "%s->%s", superModule, superChildNode.getPath());
+                    requireNonNull(type, () -> module + "->" + childNode.getPath());
+                    requireNonNull(superType, () -> superModule + "->" + superChildNode.getPath());
                     type.addImplementsType(superType);
                     if (superChildNode instanceof ListSchemaNode
                             && !((ListSchemaNode) superChildNode).getKeyDefinition().isEmpty()) {
                     type.addImplementsType(superType);
                     if (superChildNode instanceof ListSchemaNode
                             && !((ListSchemaNode) superChildNode).getKeyDefinition().isEmpty()) {
-                        if (namespaceType.equals(BindingNamespaceType.Grouping)) {
+                        if (BindingNamespaceType.isGrouping(namespaceType)) {
                             genCtx.get(module).getKeyType(childNode.getPath())
                                     .addImplementsType(genCtx.get(superModule).getKeyType(superChildNode.getPath()));
                             genCtx.get(module).getKeyType(childNode.getPath())
                                     .addImplementsType(genCtx.get(superModule).getKeyType(superChildNode.getPath()));
-                        } else if (namespaceType.equals(BindingNamespaceType.Data)) {
+                        } else if (BindingNamespaceType.isData(namespaceType)) {
                             genCtx.get(module).getKeyGenTO(childNode.getPath())
                                     .addImplementsType(genCtx.get(superModule).getKeyType(superChildNode.getPath()));
                         }
                     }
                             genCtx.get(module).getKeyGenTO(childNode.getPath())
                                     .addImplementsType(genCtx.get(superModule).getKeyType(superChildNode.getPath()));
                         }
                     }
-                    addUsesImplements(superChildNode, superModule, childNode, module, schemaContext, genCtx, namespaceType);
+                    addUsesImplements(superChildNode, superModule, childNode, module, schemaContext, genCtx,
+                            namespaceType);
                 }
             }
         } else if (superNode instanceof ChoiceSchemaNode) {
                 }
             }
         } else if (superNode instanceof ChoiceSchemaNode) {
-            for (ChoiceCaseNode superCaseNode : ((ChoiceSchemaNode) superNode).getCases()) {
+            for (CaseSchemaNode superCaseNode : ((ChoiceSchemaNode) superNode).getCases().values()) {
                 final QName childQName = createQNameFromSuperNode(module, node, superCaseNode);
                 final QName childQName = createQNameFromSuperNode(module, node, superCaseNode);
-                ChoiceCaseNode caseNode = ((ChoiceSchemaNode) node).getCaseNodeByName(childQName);
-                Preconditions.checkNotNull(caseNode, "%s->%s", node, childQName);
+                CaseSchemaNode caseNode = ((ChoiceSchemaNode) node).getCaseNodeByName(childQName);
+                requireNonNull(caseNode, () -> node + "->" + childQName);
 
                 final GeneratedTypeBuilder type = genCtx.get(module).getCase(caseNode.getPath());
                 final GeneratedTypeBuilder superType = genCtx.get(superModule).getCase(superCaseNode.getPath());
 
                 final GeneratedTypeBuilder type = genCtx.get(module).getCase(caseNode.getPath());
                 final GeneratedTypeBuilder superType = genCtx.get(superModule).getCase(superCaseNode.getPath());
-                Preconditions.checkNotNull(type, "%s->%s", module, caseNode.getPath());
-                Preconditions.checkNotNull(superType, "%s->%s", superModule, superCaseNode.getPath());
+                requireNonNull(type, () -> module + "->" + caseNode.getPath());
+                requireNonNull(superType, () -> superModule + "->" + superCaseNode.getPath());
                 type.addImplementsType(superType);
                 addUsesImplements(superCaseNode, superModule, caseNode, module, schemaContext, genCtx, namespaceType);
             }
                 type.addImplementsType(superType);
                 addUsesImplements(superCaseNode, superModule, caseNode, module, schemaContext, genCtx, namespaceType);
             }
@@ -337,12 +342,11 @@ final class GenHelperUtil {
     }
 
     private static GroupingDefinition findGroupingNodeFromUses(final Module module, final SchemaContext schemaContext,
     }
 
     private static GroupingDefinition findGroupingNodeFromUses(final Module module, final SchemaContext schemaContext,
-            final Object parentNode, final UsesNode usesNode) {
+                                                               final Object parentNode, final UsesNode usesNode) {
         SchemaNode groupingNode;
         if (parentNode instanceof Module) {
         SchemaNode groupingNode;
         if (parentNode instanceof Module) {
-            final Module superModule = schemaContext.findModuleByNamespaceAndRevision(
-                    usesNode.getGroupingPath().getLastComponent().getModule().getNamespace(),
-                    usesNode.getGroupingPath().getLastComponent().getModule().getRevision());
+            final Module superModule = schemaContext.findModule(
+                    usesNode.getGroupingPath().getLastComponent().getModule()).get();
             groupingNode = superModule.getGroupings()
                     .stream().filter(grouping -> grouping.getPath().equals(usesNode.getGroupingPath()))
                     .findFirst().orElse(null);
             groupingNode = superModule.getGroupings()
                     .stream().filter(grouping -> grouping.getPath().equals(usesNode.getGroupingPath()))
                     .findFirst().orElse(null);
@@ -350,24 +354,26 @@ final class GenHelperUtil {
             //FIXME: Schema path is not unique for Yang 1.1, findDataSchemaNode always does search from data node first.
             final Iterable<QName> prefixedPath = usesNode.getGroupingPath().getPathFromRoot();
             final QName current = prefixedPath.iterator().next();
             //FIXME: Schema path is not unique for Yang 1.1, findDataSchemaNode always does search from data node first.
             final Iterable<QName> prefixedPath = usesNode.getGroupingPath().getPathFromRoot();
             final QName current = prefixedPath.iterator().next();
-            final Module targetModule = schemaContext.findModuleByNamespaceAndRevision(current.getNamespace(), current.getRevision());
+            final Module targetModule = schemaContext.findModule(current.getModule()).orElse(null);
             Preconditions.checkArgument(targetModule != null, "Cannot find target module for %s and %s.",
                     current.getNamespace(), current.getRevision());
             Preconditions.checkArgument(targetModule != null, "Cannot find target module for %s and %s.",
                     current.getNamespace(), current.getRevision());
-            groupingNode = targetModule.getGroupings().stream().filter(grouping -> grouping.getPath().equals(usesNode.getGroupingPath()))
+            groupingNode = targetModule.getGroupings().stream()
+                    .filter(grouping -> grouping.getPath().equals(usesNode.getGroupingPath()))
                     .collect(Collectors.toList()).get(0);
             if (groupingNode == null) {
                 groupingNode = SchemaContextUtil.findDataSchemaNode(schemaContext, usesNode.getGroupingPath());
             }
         }
 
                     .collect(Collectors.toList()).get(0);
             if (groupingNode == null) {
                 groupingNode = SchemaContextUtil.findDataSchemaNode(schemaContext, usesNode.getGroupingPath());
             }
         }
 
-        Preconditions.checkNotNull(groupingNode, "%s->%s", module, usesNode.getGroupingPath());
+        requireNonNull(groupingNode, () -> module + "->" + usesNode.getGroupingPath());
         Preconditions.checkState(groupingNode instanceof GroupingDefinition, "%s->%s", module,
         Preconditions.checkState(groupingNode instanceof GroupingDefinition, "%s->%s", module,
-            usesNode.getGroupingPath());
+                usesNode.getGroupingPath());
         return (GroupingDefinition) groupingNode;
     }
 
     static Map<Module, ModuleContext> processUsesImplements(final Object node, final Module module,
         return (GroupingDefinition) groupingNode;
     }
 
     static Map<Module, ModuleContext> processUsesImplements(final Object node, final Module module,
-            final SchemaContext schemaContext, final Map<Module, ModuleContext> genCtx, final BindingNamespaceType namespaceType) {
+                                                            final SchemaContext schemaContext, final Map<Module,
+            ModuleContext> genCtx, final BindingNamespaceType namespaceType) {
         if (node instanceof DataNodeContainer) {
             for (final UsesNode usesNode : ((DataNodeContainer) node).getUses()) {
                 final GroupingDefinition grouping = findGroupingNodeFromUses(module, schemaContext, node, usesNode);
         if (node instanceof DataNodeContainer) {
             for (final UsesNode usesNode : ((DataNodeContainer) node).getUses()) {
                 final GroupingDefinition grouping = findGroupingNodeFromUses(module, schemaContext, node, usesNode);
@@ -398,21 +404,21 @@ final class GenHelperUtil {
         return null;
     }
 
         return null;
     }
 
-    static Map<Module, ModuleContext> addRawAugmentGenTypeDefinition(final Module module, final String augmentPackageName,
-            final Type targetTypeRef, final SchemaNode targetNode, final List<AugmentationSchema> schemaPathAugmentListEntry,
-            final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders, final Map<Module, ModuleContext> genCtx,
+    static Map<Module, ModuleContext> addRawAugmentGenTypeDefinition(final Module module,
+            final String augmentPackageName, final GeneratedTypeBuilder targetTypeBuilder, final SchemaNode targetNode,
+            final List<AugmentationSchemaNode> schemaPathAugmentListEntry, final Map<String, Map<String,
+                 GeneratedTypeBuilder>> genTypeBuilders, final Map<Module, ModuleContext> genCtx,
             final SchemaContext schemaContext, final boolean verboseClassComments, final TypeProvider typeProvider,
             final BindingNamespaceType namespaceType) {
 
         //pick augmentation grouped by augmentation target, there is always at least one
             final SchemaContext schemaContext, final boolean verboseClassComments, final TypeProvider typeProvider,
             final BindingNamespaceType namespaceType) {
 
         //pick augmentation grouped by augmentation target, there is always at least one
-        final AugmentationSchema augSchema = schemaPathAugmentListEntry.get(0);
-
-        Map<String, GeneratedTypeBuilder> augmentBuilders = genTypeBuilders.computeIfAbsent(
-                augmentPackageName, k -> new HashMap<>());
+        final AugmentationSchemaNode augSchema = schemaPathAugmentListEntry.get(0);
 
         //this requires valid semantics in YANG model
         String augIdentifier = null;
 
         //this requires valid semantics in YANG model
         String augIdentifier = null;
-        for (AugmentationSchema aug : schemaPathAugmentListEntry) {
+        for (AugmentationSchemaNode aug : schemaPathAugmentListEntry) {
+            // FIXME: when there're multiple augment identifiers for augmentations of same target,
+            // it would pick the first identifier.
             augIdentifier = getAugmentIdentifier(aug.getUnknownSchemaNodes());
             break;
         }
             augIdentifier = getAugmentIdentifier(aug.getUnknownSchemaNodes());
             break;
         }
@@ -427,26 +433,40 @@ final class GenHelperUtil {
 
         augTypeBuilder.addImplementsType(BindingTypes.TREE_NODE);
         augTypeBuilder.addImplementsType(parameterizedTypeFor(BindingTypes.INSTANTIABLE, augTypeBuilder));
 
         augTypeBuilder.addImplementsType(BindingTypes.TREE_NODE);
         augTypeBuilder.addImplementsType(parameterizedTypeFor(BindingTypes.INSTANTIABLE, augTypeBuilder));
-        augTypeBuilder.addImplementsType(Types.augmentationTypeFor(targetTypeRef));
+        augTypeBuilder.addImplementsType(Types.augmentationTypeFor(targetTypeBuilder.toInstance()));
         augTypeBuilder.setBasePackageName(BindingMapping.getRootPackageName(module));
         augTypeBuilder.setWithBuilder(true);
         augTypeBuilder.setBasePackageName(BindingMapping.getRootPackageName(module));
         augTypeBuilder.setWithBuilder(true);
+        augTypeBuilder.setBindingNamespaceType(namespaceType);
         annotateDeprecatedIfNecessary(augSchema.getStatus(), augTypeBuilder);
 
         annotateDeprecatedIfNecessary(augSchema.getStatus(), augTypeBuilder);
 
+        //If target is case node then pass down parent type (the closest ancestor) to children data nodes.
+        final GeneratedTypeBuilder childOf;
+        if (targetNode instanceof CaseSchemaNode) {
+            childOf = (GeneratedTypeBuilder) targetTypeBuilder.getParentTypeForBuilder();
+        } else {
+            augTypeBuilder.setParentTypeForBuilder(targetTypeBuilder);
+            childOf = targetTypeBuilder;
+        }
+
         //produces getters for augTypeBuilder eventually
         //produces getters for augTypeBuilder eventually
-        for (AugmentationSchema aug : schemaPathAugmentListEntry) {
+        for (AugmentationSchemaNode aug : schemaPathAugmentListEntry) {
             //apply all uses
             addImplementedInterfaceFromUses(aug, augTypeBuilder, genCtx);
             //apply all uses
             addImplementedInterfaceFromUses(aug, augTypeBuilder, genCtx);
-            augSchemaNodeToMethods(module, BindingMapping.getRootPackageName(module), augTypeBuilder, augTypeBuilder, aug.getChildNodes(),
-               genCtx, schemaContext, verboseClassComments, typeProvider, genTypeBuilders, namespaceType);
+            augSchemaNodeToMethods(module, BindingMapping.getRootPackageName(module), augTypeBuilder, childOf,
+                    aug.getChildNodes(), genCtx, schemaContext, verboseClassComments, typeProvider, genTypeBuilders,
+                    targetTypeBuilder.getBindingNamespaceType());
         }
 
         }
 
+        final Map<String, GeneratedTypeBuilder> augmentBuilders = genTypeBuilders.computeIfAbsent(
+                augmentPackageName, k -> new HashMap<>());
+
         augmentBuilders.put(augTypeBuilder.getName(), augTypeBuilder);
 
         augmentBuilders.put(augTypeBuilder.getName(), augTypeBuilder);
 
-        if(!augSchema.getChildNodes().isEmpty()) {
-            genCtx.get(module).addTypeToAugmentation(augTypeBuilder, augSchema);
+        if (!augSchema.getChildNodes().isEmpty()) {
             genCtx.get(module).addTargetToAugmentation(augTypeBuilder, augSchema.getTargetPath());
         }
         genCtx.get(module).addAugmentType(augTypeBuilder);
             genCtx.get(module).addTargetToAugmentation(augTypeBuilder, augSchema.getTargetPath());
         }
         genCtx.get(module).addAugmentType(augTypeBuilder);
+        genCtx.get(module).addTypeToAugmentations(augTypeBuilder, schemaPathAugmentListEntry);
         return genCtx;
     }
 
         return genCtx;
     }
 
@@ -454,28 +474,25 @@ final class GenHelperUtil {
      * Adds the methods to <code>typeBuilder</code> what represents subnodes of
      * node for which <code>typeBuilder</code> was created.
      *
      * Adds the methods to <code>typeBuilder</code> what represents subnodes of
      * node for which <code>typeBuilder</code> was created.
      *
-     * @param module
-     *            current module
-     * @param basePackageName
-     *            string contains the module package name
-     * @param typeBuilder
-     *            generated type builder which represents any node. The subnodes
-     *            of this node are added to the <code>typeBuilder</code> as
-     *            methods. The subnode can be of type leaf, leaf-list, list,
-     *            container, choice.
-     * @param childOf
-     *            parent type
-     * @param schemaNodes
-     *            set of data schema nodes which are the children of the node
-     *            for which <code>typeBuilder</code> was created
-     * @return generated type builder which is the same object as the input
-     *         parameter <code>typeBuilder</code>. The getter method could be
-     *         added to it.
+     * @param module          current module
+     * @param basePackageName string contains the module package name
+     * @param typeBuilder     generated type builder which represents any node. The subnodes
+     *                        of this node are added to the <code>typeBuilder</code> as
+     *                        methods. The subnode can be of type leaf, leaf-list, list,
+     *                        container, choice.
+     * @param childOf         parent type
+     * @param schemaNodes     set of data schema nodes which are the children of the node
+     *                        for which <code>typeBuilder</code> was created
+     * @return generated type builder which is the same object as the input added to it.
      */
     private static GeneratedTypeBuilder augSchemaNodeToMethods(final Module module, final String basePackageName,
      */
     private static GeneratedTypeBuilder augSchemaNodeToMethods(final Module module, final String basePackageName,
-            final GeneratedTypeBuilder typeBuilder, final GeneratedTypeBuilder childOf, final Iterable<DataSchemaNode> schemaNodes,
-            final Map<Module, ModuleContext> genCtx, final SchemaContext schemaContext, final boolean
-            verboseClassComments, final TypeProvider typeProvider, final Map<String, Map<String,
+                                                               final GeneratedTypeBuilder typeBuilder, final
+                                                               GeneratedTypeBuilder childOf, final
+                                                               Iterable<DataSchemaNode> schemaNodes,
+                                                               final Map<Module, ModuleContext> genCtx, final
+                                                               SchemaContext schemaContext, final boolean
+                                                                       verboseClassComments, final TypeProvider
+                                                                       typeProvider, final Map<String, Map<String,
             GeneratedTypeBuilder>> genTypeBuilders, final BindingNamespaceType namespaceType) {
         if (schemaNodes != null && typeBuilder != null) {
             for (final DataSchemaNode schemaNode : schemaNodes) {
             GeneratedTypeBuilder>> genTypeBuilders, final BindingNamespaceType namespaceType) {
         if (schemaNodes != null && typeBuilder != null) {
             for (final DataSchemaNode schemaNode : schemaNodes) {
@@ -492,6 +509,7 @@ final class GenHelperUtil {
      * Instantiates generated type builder with <code>packageName</code> and
      * <code>schemaNode</code>.
      *
      * Instantiates generated type builder with <code>packageName</code> and
      * <code>schemaNode</code>.
      *
+     * <p>
      * The new builder always implements
      * {@link TreeNode TreeNode}.<br>
      * If <code>schemaNode</code> is instance of GroupingDefinition it also
      * The new builder always implements
      * {@link TreeNode TreeNode}.<br>
      * If <code>schemaNode</code> is instance of GroupingDefinition it also
@@ -502,48 +520,39 @@ final class GenHelperUtil {
      * DataNodeContainer} it can also implement nodes which are specified in
      * <i>uses</i>.
      *
      * DataNodeContainer} it can also implement nodes which are specified in
      * <i>uses</i>.
      *
-     * @param basePackageName
-     *            string contains the module package name
-     * @param schemaNode
-     *            schema node for which is created generated type builder
-     * @param parent
-     *            parent type (can be null)
-     * @param schemaContext schema context
+     * @param basePackageName string contains the module package name
+     * @param schemaNode      schema node for which is created generated type builder
+     * @param childOf         parent generated type of data tree node, which should be
+     *                        set null if current schema node is not a data tree node.
+     * @param schemaContext   schema context
      * @return generated type builder <code>schemaNode</code>
      */
      * @return generated type builder <code>schemaNode</code>
      */
-    private static GeneratedTypeBuilder addDefaultInterfaceDefinition(final String basePackageName, final SchemaNode
-            schemaNode, final Type parent, final Module module, final Map<Module, ModuleContext> genCtx,
-            final SchemaContext schemaContext, final boolean verboseClassComments, final Map<String, Map<String,
-            GeneratedTypeBuilder>> genTypeBuilders, final TypeProvider typeProvider, final BindingNamespaceType namespaceType) {
-
-        String suffix = "";
-        if (schemaNode instanceof GroupingDefinition) {
-            suffix = "grouping";
-        } else if (namespaceType.equals(BindingNamespaceType.Grouping)) {
-            suffix = "data";
-        }
-
-        GeneratedTypeBuilder it = addRawInterfaceDefinition(basePackageName, schemaNode, schemaContext, "", suffix,
+    public static GeneratedTypeBuilder addDefaultInterfaceDefinition(final String basePackageName, final SchemaNode
+            schemaNode, @Nullable final Type childOf, final Module module, final Map<Module, ModuleContext> genCtx,
+                                                                     final SchemaContext schemaContext, final boolean
+                                                                             verboseClassComments, final Map<String,
+            Map<String,
+                    GeneratedTypeBuilder>> genTypeBuilders, final TypeProvider typeProvider, final BindingNamespaceType
+                                                                             namespaceType) {
+
+        GeneratedTypeBuilder it = addRawInterfaceDefinition(basePackageName, schemaNode, schemaContext, "", "",
                 verboseClassComments, genTypeBuilders, namespaceType, genCtx.get(module));
                 verboseClassComments, genTypeBuilders, namespaceType, genCtx.get(module));
-        if (namespaceType.equals(BindingNamespaceType.Data)) {
-            if (parent == null) {
+        if (BindingNamespaceType.isData(namespaceType)) {
+            if (childOf == null) {
                 it.addImplementsType(BindingTypes.TREE_NODE);
             } else {
                 it.addImplementsType(BindingTypes.TREE_NODE);
             } else {
-                if (parent instanceof ListSchemaNode) {
-                    it.addImplementsType(parameterizedTypeFor(BindingTypes.TREE_CHILD_NODE, parent, parameterizedTypeFor
-                            (BindingTypes.IDENTIFIABLE_ITEM, parent)));
-                } else {
-                    it.addImplementsType(parameterizedTypeFor(BindingTypes.TREE_CHILD_NODE, parent, parameterizedTypeFor
-                            (BindingTypes.ITEM, parent)));
-                    it.addImplementsType(parameterizedTypeFor(BindingTypes.INSTANTIABLE, it));
+                if (!(schemaNode instanceof ListSchemaNode)
+                        || ((ListSchemaNode) schemaNode).getKeyDefinition().isEmpty()) {
+                    it.addImplementsType(parameterizedTypeFor(BindingTypes.TREE_CHILD_NODE, childOf,
+                            parameterizedTypeFor(BindingTypes.ITEM, it)));
                 }
             }
 
                 }
             }
 
-            if (!(schemaNode instanceof GroupingDefinition)) {
-                it.addImplementsType(BindingTypes.augmentable(it));
+            if (!(schemaNode instanceof CaseSchemaNode)) {
+                it.addImplementsType(parameterizedTypeFor(BindingTypes.INSTANTIABLE, it));
             }
             }
-        } else {
-            it.addImplementsType(BindingTypes.TREE_NODE);
+
+            it.addImplementsType(BindingTypes.augmentable(it));
         }
 
         if (schemaNode instanceof DataNodeContainer) {
         }
 
         if (schemaNode instanceof DataNodeContainer) {
@@ -557,11 +566,14 @@ final class GenHelperUtil {
 
     static GeneratedTypeBuilder resolveNotification(final GeneratedTypeBuilder listenerInterface, final String
             parentName, final String basePackageName, final NotificationDefinition notification, final Module module,
 
     static GeneratedTypeBuilder resolveNotification(final GeneratedTypeBuilder listenerInterface, final String
             parentName, final String basePackageName, final NotificationDefinition notification, final Module module,
-            final SchemaContext schemaContext, final boolean verboseClassComments, final Map<String, Map<String, GeneratedTypeBuilder>>
-            genTypeBuilders, final TypeProvider typeProvider, final Map<Module, ModuleContext> genCtx) {
-        final GeneratedTypeBuilder notificationInterface = addDefaultInterfaceDefinition
-                (basePackageName, notification, null, module, genCtx, schemaContext,
-                        verboseClassComments, genTypeBuilders, typeProvider, BindingNamespaceType.Data);
+                                                    final SchemaContext schemaContext, final boolean
+                                                            verboseClassComments, final Map<String, Map<String,
+            GeneratedTypeBuilder>>
+                                                            genTypeBuilders, final TypeProvider typeProvider, final
+                                                    Map<Module, ModuleContext> genCtx) {
+        final GeneratedTypeBuilder notificationInterface = addDefaultInterfaceDefinition(basePackageName, notification,
+                null, module, genCtx, schemaContext, verboseClassComments, genTypeBuilders, typeProvider,
+                BindingNamespaceType.Notification);
         annotateDeprecatedIfNecessary(notification.getStatus(), notificationInterface);
         notificationInterface.addImplementsType(NOTIFICATION);
         genCtx.get(module).addChildNodeType(notification, notificationInterface);
         annotateDeprecatedIfNecessary(notification.getStatus(), notificationInterface);
         notificationInterface.addImplementsType(NOTIFICATION);
         genCtx.get(module).addChildNodeType(notification, notificationInterface);
@@ -569,7 +581,7 @@ final class GenHelperUtil {
         // Notification object
         resolveDataSchemaNodes(module, basePackageName, notificationInterface,
                 notificationInterface, notification.getChildNodes(), genCtx, schemaContext,
         // Notification object
         resolveDataSchemaNodes(module, basePackageName, notificationInterface,
                 notificationInterface, notification.getChildNodes(), genCtx, schemaContext,
-                verboseClassComments, genTypeBuilders, typeProvider, BindingNamespaceType.Data);
+                verboseClassComments, genTypeBuilders, typeProvider, BindingNamespaceType.Notification);
 
         //in case of tied notification, incorporate parent's localName
         final StringBuilder sb = new StringBuilder("on_");
 
         //in case of tied notification, incorporate parent's localName
         final StringBuilder sb = new StringBuilder("on_");
@@ -578,9 +590,10 @@ final class GenHelperUtil {
         }
         sb.append(notificationInterface.getName());
 
         }
         sb.append(notificationInterface.getName());
 
-        listenerInterface.addMethod(JavaIdentifierNormalizer.normalizeSpecificIdentifier(sb.toString(), JavaIdentifier.METHOD))
+        listenerInterface.addMethod(JavaIdentifierNormalizer.normalizeSpecificIdentifier(sb.toString(),
+                JavaIdentifier.METHOD))
                 .setAccessModifier(AccessModifier.PUBLIC).addParameter(notificationInterface, "notification")
                 .setAccessModifier(AccessModifier.PUBLIC).addParameter(notificationInterface, "notification")
-                .setComment(encodeAngleBrackets(notification.getDescription())).setReturnType(Types.VOID);
+                .setComment(encodeAngleBrackets(notification.getDescription().orElse(null))).setReturnType(Types.VOID);
         return listenerInterface;
     }
 
         return listenerInterface;
     }
 
@@ -588,31 +601,30 @@ final class GenHelperUtil {
      * Returns reference to generated type builder for specified
      * <code>schemaNode</code> with <code>packageName</code>.
      *
      * Returns reference to generated type builder for specified
      * <code>schemaNode</code> with <code>packageName</code>.
      *
+     * <p>
      * Firstly the generated type builder is searched in
      * {@link BindingGeneratorImpl#genTypeBuilders genTypeBuilders}. If it isn't
      * found it is created and added to <code>genTypeBuilders</code>.
      *
      * Firstly the generated type builder is searched in
      * {@link BindingGeneratorImpl#genTypeBuilders genTypeBuilders}. If it isn't
      * found it is created and added to <code>genTypeBuilders</code>.
      *
-     * @param basePackageName
-     *            string contains the module package name
-     * @param schemaNode
-     *            schema node which provide data about the schema node name
-     * @param schemaContext schema context
-     * @param prefix
-     *            return type name prefix
+     * @param basePackageName string contains the module package name
+     * @param schemaNode      schema node which provide data about the schema node name
+     * @param schemaContext   schema context
+     * @param prefix          return type name prefix
      * @return generated type builder for <code>schemaNode</code>
      * @return generated type builder for <code>schemaNode</code>
-     * @throws IllegalArgumentException
-     *             <ul>
-     *             <li>if <code>schemaNode</code> is null</li>
-     *             <li>if <code>packageName</code> is null</li>
-     *             <li>if QName of schema node is null</li>
-     *             <li>if schemaNode name is null</li>
-     *             </ul>
-     *
+     * @throws IllegalArgumentException <ul>
+     *                                  <li>if <code>schemaNode</code> is null</li>
+     *                                  <li>if <code>packageName</code> is null</li>
+     *                                  <li>if QName of schema node is null</li>
+     *                                  <li>if schemaNode name is null</li>
+     *                                  </ul>
      */
     static GeneratedTypeBuilder addRawInterfaceDefinition(final String basePackageName, final SchemaNode schemaNode,
      */
     static GeneratedTypeBuilder addRawInterfaceDefinition(final String basePackageName, final SchemaNode schemaNode,
-            final SchemaContext schemaContext, final String prefix, final String suffix,
-            final boolean verboseClassComments, final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders,
-            final BindingNamespaceType namespaceType, final ModuleContext context) {
+                                                          final SchemaContext schemaContext, final String prefix,
+                                                          final String suffix,
+                                                          final boolean verboseClassComments, final Map<String,
+            Map<String, GeneratedTypeBuilder>> genTypeBuilders,
+                                                          final BindingNamespaceType namespaceType, final
+                                                          ModuleContext context) {
 
         Preconditions.checkArgument(schemaNode != null, "Data Schema Node cannot be NULL.");
         Preconditions.checkArgument(basePackageName != null, "Base package Name for Generated Type cannot be NULL.");
 
         Preconditions.checkArgument(schemaNode != null, "Data Schema Node cannot be NULL.");
         Preconditions.checkArgument(basePackageName != null, "Base package Name for Generated Type cannot be NULL.");
@@ -633,14 +645,17 @@ final class GenHelperUtil {
         final GeneratedTypeBuilderImpl newType = new GeneratedTypeBuilderImpl(packageName, schemaNodeName, context);
         final Module module = SchemaContextUtil.findParentModule(schemaContext, schemaNode);
         qNameConstant(newType, BindingMapping.QNAME_STATIC_FIELD_NAME, schemaNode.getQName());
         final GeneratedTypeBuilderImpl newType = new GeneratedTypeBuilderImpl(packageName, schemaNodeName, context);
         final Module module = SchemaContextUtil.findParentModule(schemaContext, schemaNode);
         qNameConstant(newType, BindingMapping.QNAME_STATIC_FIELD_NAME, schemaNode.getQName());
-        newType.addComment(schemaNode.getDescription());
-        newType.setDescription(createDescription(schemaNode, newType.getFullyQualifiedName(), schemaContext,
-                verboseClassComments, namespaceType));
-        newType.setReference(schemaNode.getReference());
+        if (verboseClassComments) {
+            YangSourceDefinition.of(module, schemaNode).ifPresent(newType::setYangSourceDefinition);
+            TypeComments.description(schemaNode).ifPresent(newType::addComment);
+            schemaNode.getDescription().ifPresent(newType::setDescription);
+            schemaNode.getReference().ifPresent(newType::setReference);
+        }
         newType.setSchemaPath((List<QName>) schemaNode.getPath().getPathFromRoot());
         newType.setModuleName(module.getName());
         newType.setBasePackageName(BindingMapping.getRootPackageName(module));
         newType.setWithBuilder(AuxiliaryGenUtils.hasBuilderClass(schemaNode, namespaceType));
         newType.setSchemaPath((List<QName>) schemaNode.getPath().getPathFromRoot());
         newType.setModuleName(module.getName());
         newType.setBasePackageName(BindingMapping.getRootPackageName(module));
         newType.setWithBuilder(AuxiliaryGenUtils.hasBuilderClass(schemaNode, namespaceType));
+        newType.setBindingNamespaceType(namespaceType);
 
         if (!genTypeBuilders.containsKey(packageName)) {
             final Map<String, GeneratedTypeBuilder> builders = new HashMap<>();
 
         if (!genTypeBuilders.containsKey(packageName)) {
             final Map<String, GeneratedTypeBuilder> builders = new HashMap<>();
@@ -657,10 +672,13 @@ final class GenHelperUtil {
     }
 
     private static void addSchemaNodeToBuilderAsMethod(final String basePackageName, final DataSchemaNode node,
     }
 
     private static void addSchemaNodeToBuilderAsMethod(final String basePackageName, final DataSchemaNode node,
-        final GeneratedTypeBuilder typeBuilder, final GeneratedTypeBuilder childOf, final Module module,
-        final Map<Module, ModuleContext> genCtx, final SchemaContext schemaContext, final boolean verboseClassComments,
-        final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders, final TypeProvider typeProvider,
-        final BindingNamespaceType namespaceType) {
+                                                       final GeneratedTypeBuilder typeBuilder, final
+                                                       GeneratedTypeBuilder childOf, final Module module,
+                                                       final Map<Module, ModuleContext> genCtx, final SchemaContext
+                                                               schemaContext, final boolean verboseClassComments,
+                                                       final Map<String, Map<String, GeneratedTypeBuilder>>
+                                                               genTypeBuilders, final TypeProvider typeProvider,
+                                                       final BindingNamespaceType namespaceType) {
 
         if (node != null && typeBuilder != null) {
             if (node instanceof ContainerSchemaNode) {
 
         if (node != null && typeBuilder != null) {
             if (node instanceof ContainerSchemaNode) {
@@ -668,15 +686,15 @@ final class GenHelperUtil {
                         schemaContext, verboseClassComments, genCtx, genTypeBuilders, typeProvider, namespaceType);
             } else if (node instanceof LeafListSchemaNode) {
                 resolveLeafListSchemaNode(schemaContext, typeBuilder, (LeafListSchemaNode) node, module,
                         schemaContext, verboseClassComments, genCtx, genTypeBuilders, typeProvider, namespaceType);
             } else if (node instanceof LeafListSchemaNode) {
                 resolveLeafListSchemaNode(schemaContext, typeBuilder, (LeafListSchemaNode) node, module,
-                            typeProvider, genCtx);
+                        typeProvider, genCtx, verboseClassComments);
             } else if (node instanceof LeafSchemaNode) {
                 resolveLeafSchemaNodeAsMethod("", schemaContext, typeBuilder, genCtx, (LeafSchemaNode) node, module,
             } else if (node instanceof LeafSchemaNode) {
                 resolveLeafSchemaNodeAsMethod("", schemaContext, typeBuilder, genCtx, (LeafSchemaNode) node, module,
-                        typeProvider);
+                        typeProvider, verboseClassComments);
             } else if (node instanceof ListSchemaNode) {
                 listToGenType(module, basePackageName, typeBuilder, childOf, (ListSchemaNode) node, schemaContext,
                         verboseClassComments, genCtx, genTypeBuilders, typeProvider, namespaceType);
             } else if (node instanceof ChoiceSchemaNode) {
             } else if (node instanceof ListSchemaNode) {
                 listToGenType(module, basePackageName, typeBuilder, childOf, (ListSchemaNode) node, schemaContext,
                         verboseClassComments, genCtx, genTypeBuilders, typeProvider, namespaceType);
             } else if (node instanceof ChoiceSchemaNode) {
-                choiceToGenType(module, schemaContext, verboseClassComments, basePackageName, typeBuilder,
+                choiceToGenType(module, schemaContext, verboseClassComments, basePackageName, typeBuilder, childOf,
                         (ChoiceSchemaNode) node, genTypeBuilders, genCtx, typeProvider, namespaceType);
             } else if (node instanceof AnyXmlSchemaNode || node instanceof AnyDataSchemaNode) {
                 resolveAnyNodeAsMethod(schemaContext, typeBuilder, genCtx, node, module, typeProvider);
                         (ChoiceSchemaNode) node, genTypeBuilders, genCtx, typeProvider, namespaceType);
             } else if (node instanceof AnyXmlSchemaNode || node instanceof AnyDataSchemaNode) {
                 resolveAnyNodeAsMethod(schemaContext, typeBuilder, genCtx, node, module, typeProvider);
@@ -688,56 +706,59 @@ final class GenHelperUtil {
      * Converts <code>choiceNode</code> to the list of generated types for
      * choice and its cases.
      *
      * Converts <code>choiceNode</code> to the list of generated types for
      * choice and its cases.
      *
+     * <p>
      * The package names for choice and for its cases are created as
      * concatenation of the module package (<code>basePackageName</code>) and
      * names of all parents node.
      *
      * The package names for choice and for its cases are created as
      * concatenation of the module package (<code>basePackageName</code>) and
      * names of all parents node.
      *
-     * @param module
-     *            current module
-     * @param basePackageName
-     *            string with the module package name
-     * @param parent
-     *            parent type
-     * @param choiceNode
-     *            choice node which is mapped to generated type. Also child
-     *            nodes - cases are mapped to generated types.
-     * @throws IllegalArgumentException
-     *             <ul>
-     *             <li>if <code>basePackageName</code> is null</li>
-     *             <li>if <code>choiceNode</code> is null</li>
-     *             </ul>
+     * @param module          current module
+     * @param basePackageName string with the module package name
+     * @param parent          parent type
+     * @param choiceNode      choice node which is mapped to generated type. Also child
+     *                        nodes - cases are mapped to generated types.
+     * @throws IllegalArgumentException <ul>
+     *                                  <li>if <code>basePackageName</code> is null</li>
+     *                                  <li>if <code>choiceNode</code> is null</li>
+     *                                  </ul>
      */
     private static void choiceToGenType(final Module module, final SchemaContext schemaContext, final boolean
      */
     private static void choiceToGenType(final Module module, final SchemaContext schemaContext, final boolean
-            verboseClasssComments, final String basePackageName, final GeneratedTypeBuilder parent, final
-            ChoiceSchemaNode choiceNode, final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders,
-            final Map<Module, ModuleContext> genCtx, final TypeProvider typeProvider, final BindingNamespaceType namespaceType) {
+            verboseClasssComments, final String basePackageName, final GeneratedTypeBuilder parent,
+                                        final GeneratedTypeBuilder childOf, final ChoiceSchemaNode choiceNode,
+                                        final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders,
+                                        final Map<Module, ModuleContext> genCtx, final TypeProvider typeProvider,
+                                        final BindingNamespaceType namespaceType) {
         checkArgument(basePackageName != null, "Base Package Name cannot be NULL.");
         checkArgument(choiceNode != null, "Choice Schema Node cannot be NULL.");
 
         final GeneratedTypeBuilder choiceTypeBuilder = addRawInterfaceDefinition(basePackageName, choiceNode,
                 schemaContext, "", "", verboseClasssComments, genTypeBuilders, namespaceType, genCtx.get(module));
         constructGetter(parent, choiceNode.getQName().getLocalName(),
         checkArgument(basePackageName != null, "Base Package Name cannot be NULL.");
         checkArgument(choiceNode != null, "Choice Schema Node cannot be NULL.");
 
         final GeneratedTypeBuilder choiceTypeBuilder = addRawInterfaceDefinition(basePackageName, choiceNode,
                 schemaContext, "", "", verboseClasssComments, genTypeBuilders, namespaceType, genCtx.get(module));
         constructGetter(parent, choiceNode.getQName().getLocalName(),
-                choiceNode.getDescription(), choiceTypeBuilder, choiceNode.getStatus());
-        if (namespaceType.equals(BindingNamespaceType.Data)) {
+                choiceNode.getDescription().orElse(null), choiceTypeBuilder, choiceNode.getStatus());
+        choiceTypeBuilder.setParentTypeForBuilder(childOf);
+        if (BindingNamespaceType.isData(namespaceType)) {
             choiceTypeBuilder.addImplementsType(parameterizedTypeFor(BindingTypes.INSTANTIABLE, choiceTypeBuilder));
         }
         annotateDeprecatedIfNecessary(choiceNode.getStatus(), choiceTypeBuilder);
         genCtx.get(module).addChildNodeType(choiceNode, choiceTypeBuilder);
         generateTypesFromChoiceCases(module, schemaContext, genCtx, basePackageName, choiceTypeBuilder.toInstance(),
             choiceTypeBuilder.addImplementsType(parameterizedTypeFor(BindingTypes.INSTANTIABLE, choiceTypeBuilder));
         }
         annotateDeprecatedIfNecessary(choiceNode.getStatus(), choiceTypeBuilder);
         genCtx.get(module).addChildNodeType(choiceNode, choiceTypeBuilder);
         generateTypesFromChoiceCases(module, schemaContext, genCtx, basePackageName, choiceTypeBuilder.toInstance(),
-            choiceNode, verboseClasssComments, typeProvider, genTypeBuilders, namespaceType);
+                choiceNode, verboseClasssComments, typeProvider, genTypeBuilders, namespaceType);
     }
 
     private static void containerToGenType(final Module module, final String basePackageName,
     }
 
     private static void containerToGenType(final Module module, final String basePackageName,
-        final GeneratedTypeBuilder parent, final GeneratedTypeBuilder childOf, final ContainerSchemaNode node,
-        final SchemaContext schemaContext, final boolean verboseClassComments, final Map<Module, ModuleContext> genCtx,
-        final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders, final TypeProvider typeProvider,
-        final BindingNamespaceType namespaceType) {
+                                           final GeneratedTypeBuilder parent, final GeneratedTypeBuilder childOf,
+                                           final ContainerSchemaNode node,
+                                           final SchemaContext schemaContext, final boolean verboseClassComments,
+                                           final Map<Module, ModuleContext> genCtx,
+                                           final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders,
+                                           final TypeProvider typeProvider,
+                                           final BindingNamespaceType namespaceType) {
 
         final GeneratedTypeBuilder genType = processDataSchemaNode(module, basePackageName, childOf, node,
                 schemaContext, verboseClassComments, genCtx, genTypeBuilders, typeProvider, namespaceType);
         if (genType != null) {
             StringBuilder getterName = new StringBuilder(node.getQName().getLocalName());
 
         final GeneratedTypeBuilder genType = processDataSchemaNode(module, basePackageName, childOf, node,
                 schemaContext, verboseClassComments, genCtx, genTypeBuilders, typeProvider, namespaceType);
         if (genType != null) {
             StringBuilder getterName = new StringBuilder(node.getQName().getLocalName());
-            constructGetter(parent, getterName.toString(), node.getDescription(), genType, node.getStatus());
+            constructGetter(parent, getterName.toString(), node.getDescription().orElse(null), genType, node
+                    .getStatus());
             resolveDataSchemaNodes(module, basePackageName, genType, genType, node.getChildNodes(), genCtx,
                     schemaContext, verboseClassComments, genTypeBuilders, typeProvider, namespaceType);
             processUsesImplements(node, module, schemaContext, genCtx, namespaceType);
             resolveDataSchemaNodes(module, basePackageName, genType, genType, node.getChildNodes(), genCtx,
                     schemaContext, verboseClassComments, genTypeBuilders, typeProvider, namespaceType);
             processUsesImplements(node, module, schemaContext, genCtx, namespaceType);
@@ -746,9 +767,10 @@ final class GenHelperUtil {
 
     private static void listToGenType(final Module module, final String basePackageName, final GeneratedTypeBuilder
             parent, final GeneratedTypeBuilder childOf, final ListSchemaNode node, final SchemaContext schemaContext,
 
     private static void listToGenType(final Module module, final String basePackageName, final GeneratedTypeBuilder
             parent, final GeneratedTypeBuilder childOf, final ListSchemaNode node, final SchemaContext schemaContext,
-            final boolean verboseClassComments, final Map<Module, ModuleContext> genCtx,
-            final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders, final TypeProvider typeProvider,
-            final BindingNamespaceType namespaceType) {
+                                      final boolean verboseClassComments, final Map<Module, ModuleContext> genCtx,
+                                      final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders, final
+                                      TypeProvider typeProvider,
+                                      final BindingNamespaceType namespaceType) {
 
         final GeneratedTypeBuilder genType = processDataSchemaNode(module, basePackageName, childOf, node,
                 schemaContext, verboseClassComments, genCtx, genTypeBuilders, typeProvider, namespaceType);
 
         final GeneratedTypeBuilder genType = processDataSchemaNode(module, basePackageName, childOf, node,
                 schemaContext, verboseClassComments, genCtx, genTypeBuilders, typeProvider, namespaceType);
@@ -756,22 +778,25 @@ final class GenHelperUtil {
             final String nodeName = node.getQName().getLocalName();
 
             Type getterReturnType = Types.listTypeFor(genType);
             final String nodeName = node.getQName().getLocalName();
 
             Type getterReturnType = Types.listTypeFor(genType);
-            if (namespaceType.equals(BindingNamespaceType.Grouping)) {
+            if (BindingNamespaceType.isGrouping(namespaceType)) {
                 getterReturnType = Types.listTypeFor(wildcardTypeFor(genType.getPackageName(), genType.getName(),
                 getterReturnType = Types.listTypeFor(wildcardTypeFor(genType.getPackageName(), genType.getName(),
-                                true, true, null));
+                        true, true, null));
             }
             }
-            constructGetter(parent, nodeName, node.getDescription(), getterReturnType, node.getStatus());
+            constructGetter(parent, nodeName, node.getDescription().orElse(null), getterReturnType, node.getStatus());
 
             final List<QName> listKeys = node.getKeyDefinition();
             final String packageName = new StringBuilder(packageNameForGeneratedType(basePackageName, node.getPath(),
                     BindingNamespaceType.Key)).append('.').append(nodeName).toString();
             //FIXME: Is it neccessary to generate interface of key and implemented by class?
 
             final List<QName> listKeys = node.getKeyDefinition();
             final String packageName = new StringBuilder(packageNameForGeneratedType(basePackageName, node.getPath(),
                     BindingNamespaceType.Key)).append('.').append(nodeName).toString();
             //FIXME: Is it neccessary to generate interface of key and implemented by class?
-            if (namespaceType.equals(BindingNamespaceType.Grouping)) {
-                final GeneratedTypeBuilder genTypeBuilder = resolveListKeyTypeBuilder(packageName, node, genCtx.get(module));
+            if (BindingNamespaceType.isGrouping(namespaceType)) {
+                final GeneratedTypeBuilder genTypeBuilder = resolveListKeyTypeBuilder(packageName, node,
+                        genCtx.get(module));
                 for (final DataSchemaNode schemaNode : node.getChildNodes()) {
                     if (resolveDataSchemaNodesCheck(module, schemaContext, schemaNode)) {
                 for (final DataSchemaNode schemaNode : node.getChildNodes()) {
                     if (resolveDataSchemaNodesCheck(module, schemaContext, schemaNode)) {
-                        addSchemaNodeToListTypeBuilders(nodeName, basePackageName, schemaNode, genType, genTypeBuilder, listKeys,
-                                module, typeProvider, schemaContext, genCtx, genTypeBuilders, verboseClassComments, namespaceType);
+                        addSchemaNodeToListTypeBuilders(nodeName, basePackageName, schemaNode, genType,
+                                genTypeBuilder, listKeys,
+                                module, typeProvider, schemaContext, genCtx, genTypeBuilders, verboseClassComments,
+                                namespaceType);
                     }
                 }
                 if (genTypeBuilder != null) {
                     }
                 }
                 if (genTypeBuilder != null) {
@@ -785,12 +810,18 @@ final class GenHelperUtil {
                     final Type identifiableMarker = Types.parameterizedTypeFor(IDENTIFIABLE, genTOBuilder);
                     genTOBuilder.addImplementsType(IDENTIFIER);
                     genType.addImplementsType(identifiableMarker);
                     final Type identifiableMarker = Types.parameterizedTypeFor(IDENTIFIABLE, genTOBuilder);
                     genTOBuilder.addImplementsType(IDENTIFIER);
                     genType.addImplementsType(identifiableMarker);
+                    if (BindingNamespaceType.isData(namespaceType)) {
+                        genType.addImplementsType(parameterizedTypeFor(BindingTypes.TREE_CHILD_NODE, childOf,
+                                parameterizedTypeFor(BindingTypes.IDENTIFIABLE_ITEM, genType, genTOBuilder)));
+                    }
                 }
 
                 for (final DataSchemaNode schemaNode : node.getChildNodes()) {
                     if (resolveDataSchemaNodesCheck(module, schemaContext, schemaNode)) {
                 }
 
                 for (final DataSchemaNode schemaNode : node.getChildNodes()) {
                     if (resolveDataSchemaNodesCheck(module, schemaContext, schemaNode)) {
-                        addSchemaNodeToListBuilders(nodeName, basePackageName, schemaNode, genType, genTOBuilder, listKeys,
-                                module, typeProvider, schemaContext, genCtx, genTypeBuilders, verboseClassComments, namespaceType);
+                        addSchemaNodeToListBuilders(nodeName, basePackageName, schemaNode, genType, genTOBuilder,
+                                listKeys,
+                                module, typeProvider, schemaContext, genCtx, genTypeBuilders, verboseClassComments,
+                                namespaceType);
                     }
                 }
                 processUsesImplements(node, module, schemaContext, genCtx, namespaceType);
                     }
                 }
                 processUsesImplements(node, module, schemaContext, genCtx, namespaceType);
@@ -800,7 +831,6 @@ final class GenHelperUtil {
                     final GeneratedPropertyBuilder prop = new GeneratedPropertyBuilderImpl("serialVersionUID");
                     prop.setValue(Long.toString(computeDefaultSUID(genTOBuilder)));
                     genTOBuilder.setSUID(prop);
                     final GeneratedPropertyBuilder prop = new GeneratedPropertyBuilderImpl("serialVersionUID");
                     prop.setValue(Long.toString(computeDefaultSUID(genTOBuilder)));
                     genTOBuilder.setSUID(prop);
-
                     typeBuildersToGenTypes(module, genType, genTOBuilder.toInstance(), genCtx, namespaceType);
                     genCtx.get(module).addGeneratedTOBuilder(node.getPath(), genTOBuilder);
                 }
                     typeBuildersToGenTypes(module, genType, genTOBuilder.toInstance(), genCtx, namespaceType);
                     genCtx.get(module).addGeneratedTOBuilder(node.getPath(), genTOBuilder);
                 }
@@ -809,42 +839,53 @@ final class GenHelperUtil {
     }
 
     private static void typeBuildersToGenTypes(final Module module, final GeneratedTypeBuilder typeBuilder,
     }
 
     private static void typeBuildersToGenTypes(final Module module, final GeneratedTypeBuilder typeBuilder,
-            final Type keyType, final Map<Module, ModuleContext> genCtx,
-            final BindingNamespaceType namespaceType) {
+                                               final Type keyType, final Map<Module, ModuleContext> genCtx,
+                                               final BindingNamespaceType namespaceType) {
         checkArgument(typeBuilder != null, "Generated Type Builder cannot be NULL.");
         if (keyType != null) {
             Type returnKeyType = keyType;
         checkArgument(typeBuilder != null, "Generated Type Builder cannot be NULL.");
         if (keyType != null) {
             Type returnKeyType = keyType;
-            if (namespaceType.equals(BindingNamespaceType.Grouping)) {
+            if (BindingNamespaceType.isGrouping(namespaceType)) {
                 returnKeyType = wildcardTypeFor(keyType.getPackageName(), keyType.getName(),
                         true, true, null);
             }
                 returnKeyType = wildcardTypeFor(keyType.getPackageName(), keyType.getName(),
                         true, true, null);
             }
-            constructGetter(typeBuilder, "identifier", "Returns Primary Key of Yang List Type", returnKeyType, Status.CURRENT);
+            constructGetter(typeBuilder, "identifier", "Returns Primary Key of Yang List Type", returnKeyType, Status
+                    .CURRENT);
 
         }
     }
 
 
         }
     }
 
+    private static void addPatternConstant(final GeneratedTypeBuilder typeBuilder, final String leafName,
+                                           final List<PatternConstraint> patternConstraints) {
+        if (!patternConstraints.isEmpty()) {
+            final StringBuilder field = new StringBuilder();
+            field.append(BindingMapping.PATTERN_CONSTANT_NAME).append("_")
+                    .append(JavaIdentifierNormalizer.normalizeSpecificIdentifier(leafName, JavaIdentifier.METHOD));
+            typeBuilder.addConstant(Types.listTypeFor(BaseYangTypes.STRING_TYPE), field.toString(),
+                    resolveRegExpressions(patternConstraints));
+        }
+    }
+
     /**
      * Converts <code>leaf</code> to the getter method which is added to
      * <code>typeBuilder</code>.
      *
     /**
      * Converts <code>leaf</code> to the getter method which is added to
      * <code>typeBuilder</code>.
      *
-     * @param typeBuilder
-     *            generated type builder to which is added getter method as
-     *            <code>leaf</code> mapping
-     * @param leaf
-     *            leaf schema node which is mapped as getter method which is
-     *            added to <code>typeBuilder</code>
-     * @param module
-     *            Module in which type was defined
+     * @param typeBuilder generated type builder to which is added getter method as
+     *                    <code>leaf</code> mapping
+     * @param leaf        leaf schema node which is mapped as getter method which is
+     *                    added to <code>typeBuilder</code>
+     * @param module      Module in which type was defined
      * @return boolean value
      * @return boolean value
-     *         <ul>
-     *         <li>false - if <code>leaf</code> or <code>typeBuilder</code> are
-     *         null</li>
-     *         <li>true - in other cases</li>
-     *         </ul>
+     * <ul>
+     * <li>false - if <code>leaf</code> or <code>typeBuilder</code> are
+     * null</li>
+     * <li>true - in other cases</li>
+     * </ul>
      */
     private static Type resolveLeafSchemaNodeAsMethod(final String nodeName, final SchemaContext schemaContext,
      */
     private static Type resolveLeafSchemaNodeAsMethod(final String nodeName, final SchemaContext schemaContext,
-            final GeneratedTypeBuilder typeBuilder, final Map<Module, ModuleContext> genCtx, final LeafSchemaNode leaf,
-            final Module module, final TypeProvider typeProvider) {
+                                                      final GeneratedTypeBuilder typeBuilder, final Map<Module,
+            ModuleContext> genCtx, final LeafSchemaNode leaf,
+                                                      final Module module, final TypeProvider typeProvider, final
+                                                      boolean verboseClassComments) {
         if (leaf == null || typeBuilder == null) {
             return null;
         }
         if (leaf == null || typeBuilder == null) {
             return null;
         }
@@ -868,12 +909,15 @@ final class GenHelperUtil {
             } else {
                 if (typeDef.getBaseType() == null && (typeDef instanceof EnumTypeDefinition
                         || typeDef instanceof UnionTypeDefinition || typeDef instanceof BitsTypeDefinition)) {
             } else {
                 if (typeDef.getBaseType() == null && (typeDef instanceof EnumTypeDefinition
                         || typeDef instanceof UnionTypeDefinition || typeDef instanceof BitsTypeDefinition)) {
-                    LeafSchemaNode originalLeaf = (LeafSchemaNode) ((DerivableSchemaNode) leaf).getOriginal().orNull();
-                    Preconditions.checkNotNull(originalLeaf);
-                    returnType = genCtx.get(findParentModule(schemaContext, originalLeaf)).getInnerType(typeDef.getPath());
+                    LeafSchemaNode originalLeaf = (LeafSchemaNode) ((DerivableSchemaNode) leaf).getOriginal()
+                            .orElse(null);
+                    requireNonNull(originalLeaf);
+                    returnType = genCtx.get(findParentModule(schemaContext, originalLeaf)).getInnerType(typeDef
+                            .getPath());
                 } else {
                     final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
                 } else {
                     final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
-                    returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf, restrictions, genCtx.get(module));
+                    returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf, restrictions,
+                            genCtx.get(module));
                 }
             }
         } else if (isInnerType(leaf, typeDef)) {
                 }
             }
         } else if (isInnerType(leaf, typeDef)) {
@@ -891,7 +935,8 @@ final class GenHelperUtil {
                         typeProvider, schemaContext, genCtx.get(module), genCtx);
                 if (genTOBuilder != null) {
                     //TODO: https://bugs.opendaylight.org/show_bug.cgi?id=2289
                         typeProvider, schemaContext, genCtx.get(module), genCtx);
                 if (genTOBuilder != null) {
                     //TODO: https://bugs.opendaylight.org/show_bug.cgi?id=2289
-                    returnType = createReturnTypeForUnion(genTOBuilder, typeDef, typeBuilder, parentModule, typeProvider);
+                    returnType = createReturnTypeForUnion(genTOBuilder, typeDef, typeBuilder, parentModule,
+                            typeProvider, verboseClassComments);
                 }
             } else if (typeDef instanceof BitsTypeDefinition) {
                 final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leaf, parentModule,
                 }
             } else if (typeDef instanceof BitsTypeDefinition) {
                 final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leaf, parentModule,
@@ -907,10 +952,12 @@ final class GenHelperUtil {
                 final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
                 returnType = typeProvider.javaTypeForSchemaDefinitionType(getBaseOrDeclaredType(typeDef), leaf,
                         restrictions, genCtx.get(module));
                 final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
                 returnType = typeProvider.javaTypeForSchemaDefinitionType(getBaseOrDeclaredType(typeDef), leaf,
                         restrictions, genCtx.get(module));
+                addPatternConstant(typeBuilder, leafName, restrictions.getPatternConstraints());
             }
         } else {
             final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
             returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf, restrictions, genCtx.get(module));
             }
         } else {
             final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
             returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf, restrictions, genCtx.get(module));
+            addPatternConstant(typeBuilder, leafName, restrictions.getPatternConstraints());
         }
 
         if (returnType == null) {
         }
 
         if (returnType == null) {
@@ -921,20 +968,15 @@ final class GenHelperUtil {
             ((TypeProviderImpl) typeProvider).putReferencedType(leaf.getPath(), returnType);
         }
 
             ((TypeProviderImpl) typeProvider).putReferencedType(leaf.getPath(), returnType);
         }
 
-        String leafDesc = leaf.getDescription();
-        if (leafDesc == null) {
-            leafDesc = "";
-        }
-
         final String leafGetterName;
         if ("key".equals(leafName.toLowerCase())) {
             StringBuilder sb = new StringBuilder(leafName)
         final String leafGetterName;
         if ("key".equals(leafName.toLowerCase())) {
             StringBuilder sb = new StringBuilder(leafName)
-                .append('_').append("RESERVED_WORD");
+                    .append('_').append("RESERVED_WORD");
             leafGetterName = sb.toString();
         } else {
             leafGetterName = leafName;
         }
             leafGetterName = sb.toString();
         } else {
             leafGetterName = leafName;
         }
-        constructGetter(typeBuilder, leafGetterName, leafDesc, returnType, leaf.getStatus());
+        constructGetter(typeBuilder, leafGetterName, leaf.getDescription().orElse(""), returnType, leaf.getStatus());
         return returnType;
     }
 
         return returnType;
     }
 
@@ -942,25 +984,24 @@ final class GenHelperUtil {
      * Converts <code>node</code> leaf list schema node to getter method of
      * <code>typeBuilder</code>.
      *
      * Converts <code>node</code> leaf list schema node to getter method of
      * <code>typeBuilder</code>.
      *
-     * @param typeBuilder
-     *            generated type builder to which is <code>node</code> added as
-     *            getter method
-     * @param node
-     *            leaf list schema node which is added to
-     *            <code>typeBuilder</code> as getter method
-     * @param module module
+     * @param typeBuilder  generated type builder to which is <code>node</code> added as
+     *                     getter method
+     * @param node         leaf list schema node which is added to
+     *                     <code>typeBuilder</code> as getter method
+     * @param module       module
      * @param typeProvider type provider instance
      * @param typeProvider type provider instance
-     * @param genCtx actual generated context
+     * @param genCtx       actual generated context
      * @return boolean value
      * @return boolean value
-     *         <ul>
-     *         <li>true - if <code>node</code>, <code>typeBuilder</code>,
-     *         nodeName equal null or <code>node</code> is added by <i>uses</i></li>
-     *         <li>false - other cases</li>
-     *         </ul>
+     * <ul>
+     * <li>true - if <code>node</code>, <code>typeBuilder</code>,
+     * nodeName equal null or <code>node</code> is added by <i>uses</i></li>
+     * <li>false - other cases</li>
+     * </ul>
      */
     private static boolean resolveLeafListSchemaNode(final SchemaContext schemaContext, final GeneratedTypeBuilder
             typeBuilder, final LeafListSchemaNode node, final Module module, final TypeProvider typeProvider,
      */
     private static boolean resolveLeafListSchemaNode(final SchemaContext schemaContext, final GeneratedTypeBuilder
             typeBuilder, final LeafListSchemaNode node, final Module module, final TypeProvider typeProvider,
-            final Map<Module, ModuleContext> genCtx) {
+                                                     final Map<Module, ModuleContext> genCtx, final boolean
+                                                             verboseClassComments) {
         if (node == null || typeBuilder == null) {
             return false;
         }
         if (node == null || typeBuilder == null) {
             return false;
         }
@@ -984,7 +1025,8 @@ final class GenHelperUtil {
                 final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, node, parentModule,
                         typeProvider, schemaContext, genCtx.get(module), genCtx);
                 if (genTOBuilder != null) {
                 final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, node, parentModule,
                         typeProvider, schemaContext, genCtx.get(module), genCtx);
                 if (genTOBuilder != null) {
-                    returnType = createReturnTypeForUnion(genTOBuilder, typeDef, typeBuilder, parentModule, typeProvider);
+                    returnType = createReturnTypeForUnion(genTOBuilder, typeDef, typeBuilder, parentModule,
+                            typeProvider, verboseClassComments);
                 }
             } else if (typeDef instanceof BitsTypeDefinition) {
                 final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, node, parentModule,
                 }
             } else if (typeDef instanceof BitsTypeDefinition) {
                 final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, node, parentModule,
@@ -992,15 +1034,21 @@ final class GenHelperUtil {
                 returnType = genTOBuilder.toInstance();
             } else {
                 final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
                 returnType = genTOBuilder.toInstance();
             } else {
                 final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
-                returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, node, restrictions, genCtx.get(module));
+                returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, node, restrictions,
+                        genCtx.get(module));
+
+                addPatternConstant(typeBuilder, nodeName.getLocalName(), restrictions.getPatternConstraints());
             }
         } else {
             final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
             returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, node, restrictions, genCtx.get(module));
             }
         } else {
             final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
             returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, node, restrictions, genCtx.get(module));
+
+            addPatternConstant(typeBuilder, nodeName.getLocalName(), restrictions.getPatternConstraints());
         }
 
         final ParameterizedType listType = Types.listTypeFor(returnType);
         }
 
         final ParameterizedType listType = Types.listTypeFor(returnType);
-        constructGetter(typeBuilder, nodeName.getLocalName(), node.getDescription(), listType, node.getStatus());
+        constructGetter(typeBuilder, nodeName.getLocalName(), node.getDescription().orElse(null), listType, node
+                .getStatus());
         return true;
     }
 
         return true;
     }
 
@@ -1008,6 +1056,7 @@ final class GenHelperUtil {
      * Converts <code>caseNodes</code> set to list of corresponding generated
      * types.
      *
      * Converts <code>caseNodes</code> set to list of corresponding generated
      * types.
      *
+     * <p>
      * For every <i>case</i> which isn't added through augment or <i>uses</i> is
      * created generated type builder. The package names for the builder is
      * created as concatenation of the module package (
      * For every <i>case</i> which isn't added through augment or <i>uses</i> is
      * created generated type builder. The package names for the builder is
      * created as concatenation of the module package (
@@ -1015,111 +1064,63 @@ final class GenHelperUtil {
      * concrete <i>case</i>. There is also relation "<i>implements type</i>"
      * between every case builder and <i>choice</i> type
      *
      * concrete <i>case</i>. There is also relation "<i>implements type</i>"
      * between every case builder and <i>choice</i> type
      *
-     * @param module
-     *            current module
-     * @param schemaContext
-     *            current schema context
-     * @param genCtx
-     *            actual generated context
-     * @param basePackageName
-     *            string with the module package name
-     * @param refChoiceType
-     *            type which represents superior <i>case</i>
-     * @param choiceNode
-     *            choice case node which is mapped to generated type
-     * @param verboseClassComments
-     *            Javadoc verbosity switch
-     * @throws IllegalArgumentException
-     *             <ul>
-     *             <li>if <code>basePackageName</code> equals null</li>
-     *             <li>if <code>refChoiceType</code> equals null</li>
-     *             <li>if <code>caseNodes</code> equals null</li>
-     *             </ul>
+     * @param module               current module
+     * @param schemaContext        current schema context
+     * @param genCtx               actual generated context
+     * @param basePackageName      string with the module package name
+     * @param refChoiceType        type which represents superior <i>case</i>
+     * @param choiceNode           choice case node which is mapped to generated type
+     * @param verboseClassComments Javadoc verbosity switch
+     * @throws IllegalArgumentException <ul>
+     *                                  <li>if <code>basePackageName</code> equals null</li>
+     *                                  <li>if <code>refChoiceType</code> equals null</li>
+     *                                  <li>if <code>caseNodes</code> equals null</li>
+     *                                  </ul>
      */
     private static void generateTypesFromChoiceCases(final Module module, final SchemaContext schemaContext,
      */
     private static void generateTypesFromChoiceCases(final Module module, final SchemaContext schemaContext,
-            final Map<Module, ModuleContext> genCtx, final String basePackageName, final Type refChoiceType,
-            final ChoiceSchemaNode choiceNode, final boolean verboseClassComments, final TypeProvider typeProvider,
-            final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders, final BindingNamespaceType namespaceType) {
+                                                     final Map<Module, ModuleContext> genCtx, final String
+                                                             basePackageName, final GeneratedType refChoiceType,
+                                                     final ChoiceSchemaNode choiceNode, final boolean
+                                                             verboseClassComments,
+                                                     final TypeProvider typeProvider, final Map<String, Map<String,
+            GeneratedTypeBuilder>> genTypeBuilders,
+                                                     final BindingNamespaceType namespaceType) {
         checkArgument(basePackageName != null, "Base Package Name cannot be NULL.");
         checkArgument(refChoiceType != null, "Referenced Choice Type cannot be NULL.");
         checkArgument(choiceNode != null, "ChoiceNode cannot be NULL.");
 
         checkArgument(basePackageName != null, "Base Package Name cannot be NULL.");
         checkArgument(refChoiceType != null, "Referenced Choice Type cannot be NULL.");
         checkArgument(choiceNode != null, "ChoiceNode cannot be NULL.");
 
-        final Set<ChoiceCaseNode> caseNodes = choiceNode.getCases();
-        if (caseNodes == null) {
-            return;
-        }
-
-        for (final ChoiceCaseNode caseNode : caseNodes) {
+        for (final CaseSchemaNode caseNode : choiceNode.getCases().values()) {
             if (caseNode != null && resolveDataSchemaNodesCheck(module, schemaContext, caseNode)) {
                 final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(basePackageName, caseNode,
             if (caseNode != null && resolveDataSchemaNodesCheck(module, schemaContext, caseNode)) {
                 final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(basePackageName, caseNode,
-                    module, genCtx, schemaContext, verboseClassComments, genTypeBuilders, typeProvider, namespaceType);
+                        null, module, genCtx, schemaContext, verboseClassComments,
+                        genTypeBuilders, typeProvider, namespaceType);
                 caseTypeBuilder.addImplementsType(refChoiceType);
                 caseTypeBuilder.addImplementsType(refChoiceType);
-                caseTypeBuilder.setParentTypeForBuilder(refChoiceType);
+                caseTypeBuilder.setParentTypeForBuilder(refChoiceType.getParentTypeForBuilder());
                 annotateDeprecatedIfNecessary(caseNode.getStatus(), caseTypeBuilder);
                 genCtx.get(module).addCaseType(caseNode.getPath(), caseTypeBuilder);
                 annotateDeprecatedIfNecessary(caseNode.getStatus(), caseTypeBuilder);
                 genCtx.get(module).addCaseType(caseNode.getPath(), caseTypeBuilder);
-                genCtx.get(module).addChoiceToCaseMapping(refChoiceType, caseTypeBuilder, caseNode);
-                final Iterable<DataSchemaNode> caseChildNodes = caseNode.getChildNodes();
-                if (caseChildNodes != null) {
-                    final SchemaPath choiceNodeParentPath = choiceNode.getPath().getParent();
-
-                    if (!Iterables.isEmpty(choiceNodeParentPath.getPathFromRoot())) {
-                        SchemaNode parent = findDataSchemaNode(schemaContext, choiceNodeParentPath);
-
-                        if (parent instanceof AugmentationSchema) {
-                            final AugmentationSchema augSchema = (AugmentationSchema) parent;
-                            final SchemaPath targetPath = augSchema.getTargetPath();
-                            SchemaNode targetSchemaNode = findDataSchemaNode(schemaContext, targetPath);
-                            if (targetSchemaNode instanceof DataSchemaNode
-                                    && ((DataSchemaNode) targetSchemaNode).isAddedByUses()) {
-                                if (targetSchemaNode instanceof DerivableSchemaNode) {
-                                    targetSchemaNode = ((DerivableSchemaNode) targetSchemaNode).getOriginal().orNull();
-                                }
-                                if (targetSchemaNode == null) {
-                                    throw new IllegalStateException(
-                                            "Failed to find target node from grouping for augmentation " + augSchema
-                                                    + " in module " + module.getName());
-                                }
-                            }
-                            parent = targetSchemaNode;
-                        }
-
-                        Preconditions.checkState(parent != null, "Could not find Choice node parent %s",
-                                choiceNodeParentPath);
-                        GeneratedTypeBuilder childOfType = findChildNodeByPath(parent.getPath(), genCtx);
-                        if (childOfType == null) {
-                            childOfType = findGroupingByPath(parent.getPath(), genCtx);
-                        }
-                        resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, childOfType, caseChildNodes,
-                                genCtx, schemaContext, verboseClassComments, genTypeBuilders, typeProvider, namespaceType);
-                    } else {
-                        final GeneratedTypeBuilder moduleType = genCtx.get(module).getModuleNode();
-                        Preconditions.checkNotNull(moduleType, "Module type can not be null.");
-                        resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, moduleType, caseChildNodes,
-                            genCtx, schemaContext, verboseClassComments, genTypeBuilders, typeProvider, namespaceType);
-                    }
-                    processUsesImplements(caseNode, module, schemaContext, genCtx, namespaceType);
+                if (BindingNamespaceType.isData(namespaceType)) {
+                    genCtx.get(module).addChoiceToCaseMapping(refChoiceType, caseTypeBuilder, caseNode);
                 }
                 }
+
+                resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder,
+                        (GeneratedTypeBuilder) refChoiceType.getParentTypeForBuilder(), caseNode.getChildNodes(),
+                        genCtx, schemaContext, verboseClassComments, genTypeBuilders, typeProvider, namespaceType);
+                processUsesImplements(caseNode, module, schemaContext, genCtx, namespaceType);
             }
         }
     }
 
     private static Type resolveAnyNodeAsMethod(final SchemaContext schemaContext, final GeneratedTypeBuilder
             typeBuilder, final Map<Module, ModuleContext> genCtx, final DataSchemaNode node, final Module module,
             }
         }
     }
 
     private static Type resolveAnyNodeAsMethod(final SchemaContext schemaContext, final GeneratedTypeBuilder
             typeBuilder, final Map<Module, ModuleContext> genCtx, final DataSchemaNode node, final Module module,
-            final TypeProvider typeProvider) {
+                                               final TypeProvider typeProvider) {
 
         final String anyName = node.getQName().getLocalName();
         if (anyName == null) {
             return null;
         }
 
 
         final String anyName = node.getQName().getLocalName();
         if (anyName == null) {
             return null;
         }
 
-        String anyDesc = node.getDescription();
-        if (anyDesc == null) {
-            anyDesc = "";
-        }
-
         Type returnType = Types.DOCUMENT;
         Type returnType = Types.DOCUMENT;
-
-        constructGetter(typeBuilder, anyName, anyDesc, returnType, node.getStatus());
+        constructGetter(typeBuilder, anyName, node.getDescription().orElse(""), returnType, node.getStatus());
         return returnType;
     }
 
         return returnType;
     }
 
@@ -1127,44 +1128,35 @@ final class GenHelperUtil {
      * Adds <code>schemaNode</code> to <code>typeBuilder</code> as getter method
      * or to <code>genTOBuilder</code> as property.
      *
      * Adds <code>schemaNode</code> to <code>typeBuilder</code> as getter method
      * or to <code>genTOBuilder</code> as property.
      *
-     * @param nodeName
-     *            string contains the name of list
-     * @param basePackageName
-     *            string contains the module package name
-     * @param schemaNode
-     *            data schema node which should be added as getter method to
-     *            <code>typeBuilder</code> or as a property to
-     *            <code>genTOBuilder</code> if is part of the list key
-     * @param typeBuilder
-     *            generated type builder for the list schema node
-     * @param genTOBuilder
-     *            generated TO builder for the list keys
-     * @param listKeys
-     *            list of string which contains QNames of the list keys
-     * @param module
-     *            current module
-     * @param typeProvider
-     *            provider that defines contract for generated types
-     * @param schemaContext
-     *            schema context
-     * @param genCtx
-     *            map of generated entities in context of YANG modules
-     * @param genTypeBuilders
-     *            map of generated type builders
-     * @param verboseClassComments
-     *            generate verbose comments
-     * @throws IllegalArgumentException
-     *             <ul>
-     *             <li>if <code>schemaNode</code> equals null</li>
-     *             <li>if <code>typeBuilder</code> equals null</li>
-     *             </ul>
+     * @param nodeName             string contains the name of list
+     * @param basePackageName      string contains the module package name
+     * @param schemaNode           data schema node which should be added as getter method to
+     *                             <code>typeBuilder</code> or as a property to
+     *                             <code>genTOBuilder</code> if is part of the list key
+     * @param typeBuilder          generated type builder for the list schema node
+     * @param genTOBuilder         generated TO builder for the list keys
+     * @param listKeys             list of string which contains QNames of the list keys
+     * @param module               current module
+     * @param typeProvider         provider that defines contract for generated types
+     * @param schemaContext        schema context
+     * @param genCtx               map of generated entities in context of YANG modules
+     * @param genTypeBuilders      map of generated type builders
+     * @param verboseClassComments generate verbose comments
+     * @throws IllegalArgumentException <ul>
+     *                                  <li>if <code>schemaNode</code> equals null</li>
+     *                                  <li>if <code>typeBuilder</code> equals null</li>
+     *                                  </ul>
      */
     private static void addSchemaNodeToListBuilders(final String nodeName, final String basePackageName,
      */
     private static void addSchemaNodeToListBuilders(final String nodeName, final String basePackageName,
-            final DataSchemaNode schemaNode, final GeneratedTypeBuilder typeBuilder,
-            final GeneratedTOBuilder genTOBuilder, final List<QName> listKeys, final Module module,
-            final TypeProvider typeProvider, final SchemaContext schemaContext, final Map<Module, ModuleContext> genCtx,
-            final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders, final boolean verboseClassComments,
-            final BindingNamespaceType namespaceType) {
+                                                    final DataSchemaNode schemaNode, final GeneratedTypeBuilder
+                                                            typeBuilder,
+                                                    final GeneratedTOBuilder genTOBuilder, final List<QName>
+                                                            listKeys, final Module module,
+                                                    final TypeProvider typeProvider, final SchemaContext
+                                                            schemaContext, final Map<Module, ModuleContext> genCtx,
+                                                    final Map<String, Map<String, GeneratedTypeBuilder>>
+                                                            genTypeBuilders, final boolean verboseClassComments,
+                                                    final BindingNamespaceType namespaceType) {
         checkArgument(schemaNode != null, "Data Schema Node cannot be NULL.");
         checkArgument(typeBuilder != null, "Generated Type Builder cannot be NULL.");
 
         checkArgument(schemaNode != null, "Data Schema Node cannot be NULL.");
         checkArgument(typeBuilder != null, "Generated Type Builder cannot be NULL.");
 
@@ -1173,11 +1165,12 @@ final class GenHelperUtil {
             final QName leafQName = leaf.getQName();
 
             final Type type = resolveLeafSchemaNodeAsMethod(nodeName, schemaContext, typeBuilder, genCtx, leaf, module,
             final QName leafQName = leaf.getQName();
 
             final Type type = resolveLeafSchemaNodeAsMethod(nodeName, schemaContext, typeBuilder, genCtx, leaf, module,
-                    typeProvider);
+                    typeProvider, verboseClassComments);
             if (listKeys.contains(leafQName)) {
                 if (type == null) {
             if (listKeys.contains(leafQName)) {
                 if (type == null) {
-                    resolveLeafSchemaNodeAsProperty(nodeName, schemaContext, typeProvider, genCtx, genTOBuilder, leaf, true,
-                        module);
+                    resolveLeafSchemaNodeAsProperty(nodeName, schemaContext, typeProvider, genCtx, genTOBuilder,
+                            leaf, true,
+                            module);
                 } else {
                     AuxiliaryGenUtils.resolveLeafSchemaNodeAsProperty(nodeName, genTOBuilder, leaf, type, true);
                 }
                 } else {
                     AuxiliaryGenUtils.resolveLeafSchemaNodeAsProperty(nodeName, genTOBuilder, leaf, type, true);
                 }
@@ -1185,7 +1178,7 @@ final class GenHelperUtil {
         } else {
             if (schemaNode instanceof LeafListSchemaNode) {
                 resolveLeafListSchemaNode(schemaContext, typeBuilder, (LeafListSchemaNode) schemaNode, module,
         } else {
             if (schemaNode instanceof LeafListSchemaNode) {
                 resolveLeafListSchemaNode(schemaContext, typeBuilder, (LeafListSchemaNode) schemaNode, module,
-                        typeProvider, genCtx);
+                        typeProvider, genCtx, verboseClassComments);
             } else if (schemaNode instanceof ContainerSchemaNode) {
                 containerToGenType(module, basePackageName, typeBuilder, typeBuilder, (ContainerSchemaNode) schemaNode,
                         schemaContext, verboseClassComments, genCtx, genTypeBuilders, typeProvider, namespaceType);
             } else if (schemaNode instanceof ContainerSchemaNode) {
                 containerToGenType(module, basePackageName, typeBuilder, typeBuilder, (ContainerSchemaNode) schemaNode,
                         schemaContext, verboseClassComments, genCtx, genTypeBuilders, typeProvider, namespaceType);
@@ -1193,18 +1186,22 @@ final class GenHelperUtil {
                 listToGenType(module, basePackageName, typeBuilder, typeBuilder, (ListSchemaNode) schemaNode,
                         schemaContext, verboseClassComments, genCtx, genTypeBuilders, typeProvider, namespaceType);
             } else if (schemaNode instanceof ChoiceSchemaNode) {
                 listToGenType(module, basePackageName, typeBuilder, typeBuilder, (ListSchemaNode) schemaNode,
                         schemaContext, verboseClassComments, genCtx, genTypeBuilders, typeProvider, namespaceType);
             } else if (schemaNode instanceof ChoiceSchemaNode) {
-                choiceToGenType(module, schemaContext, verboseClassComments, basePackageName, typeBuilder,
+                choiceToGenType(module, schemaContext, verboseClassComments, basePackageName, typeBuilder, typeBuilder,
                         (ChoiceSchemaNode) schemaNode, genTypeBuilders, genCtx, typeProvider, namespaceType);
             }
         }
     }
 
     private static void addSchemaNodeToListTypeBuilders(final String nodeName, final String basePackageName,
                         (ChoiceSchemaNode) schemaNode, genTypeBuilders, genCtx, typeProvider, namespaceType);
             }
         }
     }
 
     private static void addSchemaNodeToListTypeBuilders(final String nodeName, final String basePackageName,
-                                                    final DataSchemaNode schemaNode, final GeneratedTypeBuilder typeBuilder,
-                                                    final GeneratedTypeBuilder genTypeBuilder, final List<QName> listKeys, final Module module,
-                                                    final TypeProvider typeProvider, final SchemaContext schemaContext, final Map<Module, ModuleContext> genCtx,
-                                                    final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders, final boolean verboseClassComments,
-                                                    final BindingNamespaceType namespaceType) {
+                                                        final DataSchemaNode schemaNode, final GeneratedTypeBuilder
+                                                                typeBuilder,
+                                                        final GeneratedTypeBuilder genTypeBuilder, final List<QName>
+                                                                listKeys, final Module module,
+                                                        final TypeProvider typeProvider, final SchemaContext
+                                                                schemaContext, final Map<Module, ModuleContext> genCtx,
+                                                        final Map<String, Map<String, GeneratedTypeBuilder>>
+                                                                genTypeBuilders, final boolean verboseClassComments,
+                                                        final BindingNamespaceType namespaceType) {
         checkArgument(schemaNode != null, "Data Schema Node cannot be NULL.");
         checkArgument(typeBuilder != null, "Generated Type Builder cannot be NULL.");
 
         checkArgument(schemaNode != null, "Data Schema Node cannot be NULL.");
         checkArgument(typeBuilder != null, "Generated Type Builder cannot be NULL.");
 
@@ -1212,15 +1209,15 @@ final class GenHelperUtil {
             final LeafSchemaNode leaf = (LeafSchemaNode) schemaNode;
             final QName leafQName = leaf.getQName();
             final Type type = resolveLeafSchemaNodeAsMethod(nodeName, schemaContext, typeBuilder, genCtx, leaf, module,
             final LeafSchemaNode leaf = (LeafSchemaNode) schemaNode;
             final QName leafQName = leaf.getQName();
             final Type type = resolveLeafSchemaNodeAsMethod(nodeName, schemaContext, typeBuilder, genCtx, leaf, module,
-                    typeProvider);
+                    typeProvider, verboseClassComments);
             if (listKeys.contains(leafQName)) {
                 resolveLeafSchemaNodeAsMethod(nodeName, schemaContext, genTypeBuilder, genCtx, leaf, module,
             if (listKeys.contains(leafQName)) {
                 resolveLeafSchemaNodeAsMethod(nodeName, schemaContext, genTypeBuilder, genCtx, leaf, module,
-                        typeProvider);
+                        typeProvider, verboseClassComments);
             }
         } else {
             if (schemaNode instanceof LeafListSchemaNode) {
                 resolveLeafListSchemaNode(schemaContext, typeBuilder, (LeafListSchemaNode) schemaNode, module,
             }
         } else {
             if (schemaNode instanceof LeafListSchemaNode) {
                 resolveLeafListSchemaNode(schemaContext, typeBuilder, (LeafListSchemaNode) schemaNode, module,
-                        typeProvider, genCtx);
+                        typeProvider, genCtx, verboseClassComments);
             } else if (schemaNode instanceof ContainerSchemaNode) {
                 containerToGenType(module, basePackageName, typeBuilder, typeBuilder, (ContainerSchemaNode) schemaNode,
                         schemaContext, verboseClassComments, genCtx, genTypeBuilders, typeProvider, namespaceType);
             } else if (schemaNode instanceof ContainerSchemaNode) {
                 containerToGenType(module, basePackageName, typeBuilder, typeBuilder, (ContainerSchemaNode) schemaNode,
                         schemaContext, verboseClassComments, genCtx, genTypeBuilders, typeProvider, namespaceType);
@@ -1228,15 +1225,18 @@ final class GenHelperUtil {
                 listToGenType(module, basePackageName, typeBuilder, typeBuilder, (ListSchemaNode) schemaNode,
                         schemaContext, verboseClassComments, genCtx, genTypeBuilders, typeProvider, namespaceType);
             } else if (schemaNode instanceof ChoiceSchemaNode) {
                 listToGenType(module, basePackageName, typeBuilder, typeBuilder, (ListSchemaNode) schemaNode,
                         schemaContext, verboseClassComments, genCtx, genTypeBuilders, typeProvider, namespaceType);
             } else if (schemaNode instanceof ChoiceSchemaNode) {
-                choiceToGenType(module, schemaContext, verboseClassComments, basePackageName, typeBuilder,
+                choiceToGenType(module, schemaContext, verboseClassComments, basePackageName, typeBuilder, typeBuilder,
                         (ChoiceSchemaNode) schemaNode, genTypeBuilders, genCtx, typeProvider, namespaceType);
             }
         }
     }
 
                         (ChoiceSchemaNode) schemaNode, genTypeBuilders, genCtx, typeProvider, namespaceType);
             }
         }
     }
 
-    private static boolean resolveLeafSchemaNodeAsProperty(final String nodeName, final SchemaContext schemaContext, final TypeProvider
-            typeProvider, final Map<Module, ModuleContext> genCtx, final GeneratedTOBuilder
-            toBuilder, final LeafSchemaNode leaf, final boolean isReadOnly, final Module module) {
+    private static boolean resolveLeafSchemaNodeAsProperty(final String nodeName, final SchemaContext schemaContext,
+                                                           final TypeProvider
+                                                                   typeProvider, final Map<Module, ModuleContext>
+                                                                   genCtx, final GeneratedTOBuilder
+                                                                   toBuilder, final LeafSchemaNode leaf, final
+                                                           boolean isReadOnly, final Module module) {
 
         if (leaf != null && toBuilder != null) {
             Type returnType;
 
         if (leaf != null && toBuilder != null) {
             Type returnType;
@@ -1245,16 +1245,14 @@ final class GenHelperUtil {
                 // GeneratedType for this type definition should be already
                 // created
                 final QName qname = typeDef.getQName();
                 // GeneratedType for this type definition should be already
                 // created
                 final QName qname = typeDef.getQName();
-                final Module unionModule = schemaContext.findModuleByNamespaceAndRevision(qname.getNamespace(),
-                        qname.getRevision());
+                final Module unionModule = schemaContext.findModule(qname.getModule()).get();
                 final ModuleContext mc = genCtx.get(unionModule);
                 returnType = mc.getTypedefs().get(typeDef.getPath());
             } else if (typeDef instanceof EnumTypeDefinition && typeDef.getBaseType() == null) {
                 // Annonymous enumeration (already generated, since it is inherited via uses).
                 LeafSchemaNode originalLeaf = (LeafSchemaNode) SchemaNodeUtils.getRootOriginalIfPossible(leaf);
                 QName qname = originalLeaf.getQName();
                 final ModuleContext mc = genCtx.get(unionModule);
                 returnType = mc.getTypedefs().get(typeDef.getPath());
             } else if (typeDef instanceof EnumTypeDefinition && typeDef.getBaseType() == null) {
                 // Annonymous enumeration (already generated, since it is inherited via uses).
                 LeafSchemaNode originalLeaf = (LeafSchemaNode) SchemaNodeUtils.getRootOriginalIfPossible(leaf);
                 QName qname = originalLeaf.getQName();
-                final Module enumModule =  schemaContext.findModuleByNamespaceAndRevision(qname.getNamespace(),
-                        qname.getRevision());
+                final Module enumModule = schemaContext.findModule(qname.getModule()).orElse(null);
                 returnType = genCtx.get(enumModule).getInnerType(originalLeaf.getType().getPath());
             } else {
                 returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf, genCtx.get(module));
                 returnType = genCtx.get(enumModule).getInnerType(originalLeaf.getType().getPath());
             } else {
                 returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf, genCtx.get(module));
@@ -1269,22 +1267,31 @@ final class GenHelperUtil {
         return baseType != null && baseType.getBaseType() != null ? baseType : typeDef;
     }
 
         return baseType != null && baseType.getBaseType() != null ? baseType : typeDef;
     }
 
-    @SuppressWarnings({ "rawtypes", "unchecked" })
+    @SuppressWarnings({"rawtypes", "unchecked"})
     private static GeneratedTypeBuilder processDataSchemaNode(final Module module, final String basePackageName,
     private static GeneratedTypeBuilder processDataSchemaNode(final Module module, final String basePackageName,
-        final GeneratedTypeBuilder childOf, final DataSchemaNode node, final SchemaContext schemaContext,
-        final boolean verboseClassComments, final Map<Module, ModuleContext> genCtx, final Map<String, Map<String,
-        GeneratedTypeBuilder>> genTypeBuilders, final TypeProvider typeProvider, final BindingNamespaceType namespaceType) {
+                                                              final GeneratedTypeBuilder childOf, final
+                                                              DataSchemaNode node, final SchemaContext
+                                                                      schemaContext,
+                                                              final boolean verboseClassComments, final Map<Module,
+            ModuleContext> genCtx, final Map<String, Map<String,
+            GeneratedTypeBuilder>> genTypeBuilders, final TypeProvider typeProvider, final BindingNamespaceType
+                                                                      namespaceType) {
 
         final GeneratedTypeBuilder genType = addDefaultInterfaceDefinition(basePackageName, node, childOf, module,
                 genCtx, schemaContext, verboseClassComments, genTypeBuilders, typeProvider, namespaceType);
 
         final GeneratedTypeBuilder genType = addDefaultInterfaceDefinition(basePackageName, node, childOf, module,
                 genCtx, schemaContext, verboseClassComments, genTypeBuilders, typeProvider, namespaceType);
-        genType.addComment(node.getDescription());
         annotateDeprecatedIfNecessary(node.getStatus(), genType);
         annotateDeprecatedIfNecessary(node.getStatus(), genType);
-        genType.setDescription(createDescription(node, genType.getFullyQualifiedName(), schemaContext,
-                verboseClassComments, namespaceType));
         genType.setModuleName(module.getName());
         genType.setModuleName(module.getName());
-        genType.setReference(node.getReference());
+        if (verboseClassComments) {
+            YangSourceDefinition.of(module, node).ifPresent(genType::setYangSourceDefinition);
+            TypeComments.description(node).ifPresent(genType::addComment);
+            node.getDescription().ifPresent(genType::setDescription);
+            node.getReference().ifPresent(genType::setReference);
+        }
         genType.setSchemaPath((List) node.getPath().getPathFromRoot());
         genType.setSchemaPath((List) node.getPath().getPathFromRoot());
-        genType.setParentTypeForBuilder(childOf);
+        if (BindingNamespaceType.isData(namespaceType)) {
+            genType.setParentTypeForBuilder(childOf);
+        }
+
         if (node instanceof DataNodeContainer) {
             genCtx.get(module).addChildNodeType(node, genType);
         }
         if (node instanceof DataNodeContainer) {
             genCtx.get(module).addChildNodeType(node, genType);
         }
@@ -1298,25 +1305,18 @@ final class GenHelperUtil {
      * saved at first positions. For every grouping the record is added to map
      * {@link ModuleContext#groupings allGroupings}
      *
      * saved at first positions. For every grouping the record is added to map
      * {@link ModuleContext#groupings allGroupings}
      *
-     * @param module
-     *            current module
-     * @param groupings
-     *            collection of groupings from which types will be generated
-     * @param typeProvider
-     *            provider that defines contract for generated types
-     * @param schemaContext
-     *            schema context
-     * @param genCtx
-     *            map of generated entities in context of YANG modules
-     * @param genTypeBuilders
-     *            map of generated type builders
-     * @param verboseClassComments
-     *            generate verbose comments
-     *
+     * @param module               current module
+     * @param groupings            collection of groupings from which types will be generated
+     * @param typeProvider         provider that defines contract for generated types
+     * @param schemaContext        schema context
+     * @param genCtx               map of generated entities in context of YANG modules
+     * @param genTypeBuilders      map of generated type builders
+     * @param verboseClassComments generate verbose comments
      */
     static Map<Module, ModuleContext> groupingsToGenTypes(final Module module, final Collection<GroupingDefinition>
             groupings, Map<Module, ModuleContext> genCtx, final SchemaContext schemaContext, final boolean
      */
     static Map<Module, ModuleContext> groupingsToGenTypes(final Module module, final Collection<GroupingDefinition>
             groupings, Map<Module, ModuleContext> genCtx, final SchemaContext schemaContext, final boolean
-            verboseClassComments, final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders, final TypeProvider typeProvider) {
+                                                                  verboseClassComments, final Map<String, Map<String,
+            GeneratedTypeBuilder>> genTypeBuilders, final TypeProvider typeProvider) {
         final String basePackageName = BindingMapping.getRootPackageName(module);
         final List<GroupingDefinition> groupingsSortedByDependencies = new GroupingDefinitionDependencySort()
                 .sort(groupings);
         final String basePackageName = BindingMapping.getRootPackageName(module);
         final List<GroupingDefinition> groupingsSortedByDependencies = new GroupingDefinitionDependencySort()
                 .sort(groupings);
@@ -1332,30 +1332,23 @@ final class GenHelperUtil {
      * builder is created and every child node of grouping is resolved to the
      * method.
      *
      * builder is created and every child node of grouping is resolved to the
      * method.
      *
-     * @param basePackageName
-     *            string contains the module package name
-     * @param grouping
-     *            GroupingDefinition which contains data about grouping
-     * @param module
-     *            current module
-     * @param typeProvider
-     *            provider that defines contract for generated types
-     * @param schemaContext
-     *            schema context
-     * @param genCtx
-     *            map of generated entities in context of YANG modules
-     * @param genTypeBuilders
-     *            map of generated type builders
-     * @param verboseClassComments
-     *            generate verbose comments
-     *
+     * @param basePackageName      string contains the module package name
+     * @param grouping             GroupingDefinition which contains data about grouping
+     * @param module               current module
+     * @param typeProvider         provider that defines contract for generated types
+     * @param schemaContext        schema context
+     * @param genCtx               map of generated entities in context of YANG modules
+     * @param genTypeBuilders      map of generated type builders
+     * @param verboseClassComments generate verbose comments
      * @return GeneratedType which is generated from grouping (object of type
      * @return GeneratedType which is generated from grouping (object of type
-     *         <code>GroupingDefinition</code>)
+     *      <code>GroupingDefinition</code>)
      */
      */
-    private static Map<Module, ModuleContext> groupingToGenType(final String basePackageName, final GroupingDefinition grouping, final Module
-            module, Map<Module, ModuleContext> genCtx, final SchemaContext schemaContext, final boolean
-            verboseClassComments, final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders, final TypeProvider typeProvider) {
-        final GeneratedTypeBuilder genType = addDefaultInterfaceDefinition(basePackageName, grouping, module, genCtx,
+    private static Map<Module, ModuleContext> groupingToGenType(final String basePackageName,
+            final GroupingDefinition grouping, final Module module, Map<Module, ModuleContext> genCtx,
+            final SchemaContext schemaContext, final boolean verboseClassComments,
+            final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders, final TypeProvider typeProvider) {
+        final GeneratedTypeBuilder genType = addDefaultInterfaceDefinition(basePackageName, grouping, null, module,
+                genCtx,
                 schemaContext, verboseClassComments, genTypeBuilders, typeProvider, BindingNamespaceType.Grouping);
         annotateDeprecatedIfNecessary(grouping.getStatus(), genType);
         genCtx.get(module).addGroupingType(grouping, genType);
                 schemaContext, verboseClassComments, genTypeBuilders, typeProvider, BindingNamespaceType.Grouping);
         annotateDeprecatedIfNecessary(grouping.getStatus(), genType);
         genCtx.get(module).addGroupingType(grouping, genType);
@@ -1374,64 +1367,66 @@ final class GenHelperUtil {
      * class {@link org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode
      * BaseIdentity} is added
      *
      * class {@link org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode
      * BaseIdentity} is added
      *
-     * @param module
-     *            current module
-     * @param basePackageName
-     *            string contains the module package name
-     * @param identity
-     *            IdentitySchemaNode which contains data about identity
-     * @param schemaContext
-     *            SchemaContext which is used to get package and name
-     *            information about base of identity
-     * @param genCtx generated context
+     * @param module          current module
+     * @param basePackageName string contains the module package name
+     * @param identity        IdentitySchemaNode which contains data about identity
+     * @param schemaContext   SchemaContext which is used to get package and name
+     *                        information about base of identity
+     * @param genCtx          generated context
      * @return returns generated context
      */
     static Map<Module, ModuleContext> identityToGenType(final Module module, final String basePackageName,
      * @return returns generated context
      */
     static Map<Module, ModuleContext> identityToGenType(final Module module, final String basePackageName,
-            final IdentitySchemaNode identity, final SchemaContext schemaContext, final Map<Module, ModuleContext> genCtx,
-            final boolean verboseClassComments) {
+                                                        final IdentitySchemaNode identity, final SchemaContext
+                                                                schemaContext, final Map<Module, ModuleContext> genCtx,
+                                                        final boolean verboseClassComments) {
 
         resolveIdentitySchemaNode(basePackageName, schemaContext, identity, module, verboseClassComments, genCtx);
         return genCtx;
     }
 
 
         resolveIdentitySchemaNode(basePackageName, schemaContext, identity, module, verboseClassComments, genCtx);
         return genCtx;
     }
 
-    private static GeneratedTOBuilder resolveIdentitySchemaNode(final String basePackageName, final SchemaContext schemaContext,
-            final IdentitySchemaNode identity, final Module module, final boolean verboseClassComments,
-            final Map<Module, ModuleContext> genCtx) {
-        Preconditions.checkNotNull(identity,"Identity can not be null!");
+    private static GeneratedTypeBuilder resolveIdentitySchemaNode(final String basePackageName, final SchemaContext
+            schemaContext,
+                                                                  final IdentitySchemaNode identity, final Module
+                                                                          module, final boolean verboseClassComments,
+                                                                  final Map<Module, ModuleContext> genCtx) {
+        requireNonNull(identity, "Identity can not be null!");
 
         //check first if identity has been resolved as base identity of some other one
 
         //check first if identity has been resolved as base identity of some other one
-        GeneratedTOBuilder newType = findIdentityByQname(identity.getQName(), genCtx);
+        GeneratedTypeBuilder newType = findIdentityByQname(identity.getQName(), genCtx);
         if (newType == null) {
             final Module parentModule = SchemaContextUtil.findParentModule(schemaContext, identity);
             Preconditions.checkState(module.equals(parentModule),
                     "If the type is null ,it must be in the same module, otherwise it must has been"
                             + "resolved by an imported module.");
 
         if (newType == null) {
             final Module parentModule = SchemaContextUtil.findParentModule(schemaContext, identity);
             Preconditions.checkState(module.equals(parentModule),
                     "If the type is null ,it must be in the same module, otherwise it must has been"
                             + "resolved by an imported module.");
 
-            final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, identity.getPath(),
+            final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, identity
+                            .getPath(),
                     BindingNamespaceType.Identity);
                     BindingNamespaceType.Identity);
-            newType = new GeneratedTOBuilderImpl(packageName, identity.getQName().getLocalName(), true, false,
+            newType = new GeneratedTypeBuilderImpl(packageName, identity.getQName().getLocalName(), true, false,
                     genCtx.get(module));
 
             final Set<IdentitySchemaNode> baseIdentities = identity.getBaseIdentities();
             if (baseIdentities.size() == 0) {
                 //no base - abstract
                     genCtx.get(module));
 
             final Set<IdentitySchemaNode> baseIdentities = identity.getBaseIdentities();
             if (baseIdentities.size() == 0) {
                 //no base - abstract
-                final GeneratedTOBuilderImpl gto = new GeneratedTOBuilderImpl(BaseIdentity.class.getPackage().getName(),
+                final GeneratedTypeBuilderImpl genType = new GeneratedTypeBuilderImpl(BaseIdentity.class.getPackage()
+                        .getName(),
                         BaseIdentity.class.getSimpleName(), genCtx.get(module));
                         BaseIdentity.class.getSimpleName(), genCtx.get(module));
-                newType.setExtendsType(gto.toInstance());
+                newType.addImplementsType(genType.toInstance());
             } else {
             } else {
-                //one base - inheritance
-                final IdentitySchemaNode baseIdentity = baseIdentities.iterator().next();
-                GeneratedTOBuilder baseType = resolveIdentitySchemaNode(basePackageName, schemaContext,
-                    baseIdentity, module, verboseClassComments, genCtx);
-                newType.setExtendsType(baseType.toInstance());
+                //multiple bases - inheritance
+                for (IdentitySchemaNode baseIdentity : baseIdentities) {
+                    GeneratedTypeBuilder baseType = resolveIdentitySchemaNode(basePackageName, schemaContext,
+                            baseIdentity, module, verboseClassComments, genCtx);
+                    newType.addImplementsType(baseType.toInstance());
+                }
             }
 
             }
 
-            newType.setAbstract(true);
-            newType.addComment(identity.getDescription());
-            newType.setDescription(createDescription(identity, newType.getFullyQualifiedName(), schemaContext,
-                    verboseClassComments, BindingNamespaceType.Identity));
-            newType.setReference(identity.getReference());
-            newType.setModuleName(module.getName());
+            if (verboseClassComments) {
+                YangSourceDefinition.of(module).ifPresent(newType::setYangSourceDefinition);
+                TypeComments.description(module).ifPresent(newType::addComment);
+                module.getDescription().ifPresent(newType::setDescription);
+                module.getReference().ifPresent(newType::setReference);
+            }
             newType.setSchemaPath((List) identity.getPath().getPathFromRoot());
 
             qNameConstant(newType, BindingMapping.QNAME_STATIC_FIELD_NAME, identity.getQName());
             newType.setSchemaPath((List) identity.getPath().getPathFromRoot());
 
             qNameConstant(newType, BindingMapping.QNAME_STATIC_FIELD_NAME, identity.getQName());