Extend BindingNamespaceType
[mdsal.git] / binding2 / mdsal-binding2-generator-impl / src / main / java / org / opendaylight / mdsal / binding / javav2 / generator / impl / AugmentToGenType.java
index bf2521fc9eebb219922b7b88a1792ab48b89d741..30a85e9b84c1e2aba5d52dba920186a5811dce6f 100644 (file)
@@ -8,32 +8,36 @@
 
 package org.opendaylight.mdsal.binding.javav2.generator.impl;
 
+import static org.opendaylight.mdsal.binding.javav2.generator.impl.GenHelperUtil.processUsesImplements;
+
 import com.google.common.annotations.Beta;
-import com.google.common.base.Optional;
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
 import java.util.ArrayList;
-import java.util.Collections;
+import java.util.Collection;
 import java.util.Comparator;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.stream.Collectors;
+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.util.ReferencedTypeImpl;
-import org.opendaylight.mdsal.binding.javav2.model.api.Type;
+import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedType;
 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedTypeBuilder;
+import org.opendaylight.mdsal.binding.javav2.spec.runtime.BindingNamespaceType;
 import org.opendaylight.mdsal.binding.javav2.util.BindingMapping;
 import org.opendaylight.yangtools.yang.common.QName;
-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.DataNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DerivableSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
 import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
@@ -46,7 +50,7 @@ final class AugmentToGenType {
     /**
      * Comparator based on augment target path.
      */
-    private static final Comparator<AugmentationSchema> AUGMENT_COMP = (o1, o2) -> {
+    private static final Comparator<AugmentationSchemaNode> AUGMENT_COMP = (o1, o2) -> {
         final Iterator<QName> thisIt = o1.getTargetPath().getPathFromRoot().iterator();
         final Iterator<QName> otherIt = o2.getTargetPath().getPathFromRoot().iterator();
 
@@ -64,6 +68,27 @@ final class AugmentToGenType {
         return otherIt.hasNext() ? -1 : 0;
     };
 
+    /**
+     * Comparator based on augment target path.
+     */
+    private static final Comparator<Map.Entry<SchemaPath, List<AugmentationSchemaNode>>> AUGMENTS_COMP = (o1, o2) -> {
+        final Iterator<QName> thisIt = o1.getKey().getPathFromRoot().iterator();
+        final Iterator<QName> otherIt = o2.getKey().getPathFromRoot().iterator();
+
+        while (thisIt.hasNext()) {
+            if (!otherIt.hasNext()) {
+                return 1;
+            }
+
+            final int comp = thisIt.next().compareTo(otherIt.next());
+            if (comp != 0) {
+                return comp;
+            }
+        }
+
+        return otherIt.hasNext() ? -1 : 0;
+    };
+
     private AugmentToGenType() {
         throw new UnsupportedOperationException("Utility class");
     }
@@ -75,9 +100,11 @@ final class AugmentToGenType {
      * @param module
      *            module from which is obtained list of all augmentation objects
      *            to iterate over them
-     * @param schemaContext
-     * @param genCtx
-     * @param genTypeBuilders
+     * @param schemaContext actual schema context
+     * @param typeProvider actual type provider instance
+     * @param genCtx generated input context
+     * @param genTypeBuilders auxiliary type builders map
+     * @param verboseClassComments verbosity switch
      *
      * @throws IllegalArgumentException
      *             <ul>
@@ -89,19 +116,35 @@ final class AugmentToGenType {
      */
     static Map<Module, ModuleContext> generate(final Module module, final SchemaContext schemaContext,
             final TypeProvider typeProvider, final Map<Module, ModuleContext> genCtx,
-            Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders, final boolean verboseClassComments) {
+            final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders, final boolean verboseClassComments) {
 
         Preconditions.checkArgument(module != null, "Module reference cannot be NULL.");
         Preconditions.checkArgument(module.getName() != null, "Module name cannot be NULL.");
         Preconditions.checkState(module.getAugmentations() != null, "Augmentations Set cannot be NULL.");
 
         final String basePackageName = BindingMapping.getRootPackageName(module);
-        final List<AugmentationSchema> augmentations = resolveAugmentations(module);
+        final List<AugmentationSchemaNode> augmentations = resolveAugmentations(module, schemaContext);
         Map<Module, ModuleContext> resultCtx = genCtx;
-        for (final AugmentationSchema augment : augmentations) {
-            resultCtx = augmentationToGenTypes(basePackageName, augment, module, schemaContext, verboseClassComments,
-                    resultCtx, genTypeBuilders, typeProvider);
+
+        //let's group augments by target path
+        Map<SchemaPath, List<AugmentationSchemaNode>> augmentationsGrouped =
+                augmentations.stream().collect(Collectors.groupingBy(AugmentationSchemaNode::getTargetPath));
+
+        List<Map.Entry<SchemaPath, List<AugmentationSchemaNode>>> sortedAugmentationsGrouped =
+                new ArrayList<>(augmentationsGrouped.entrySet());
+        sortedAugmentationsGrouped.sort(AUGMENTS_COMP);
+
+        //process child nodes of grouped augment entries
+        for (Map.Entry<SchemaPath, List<AugmentationSchemaNode>> schemaPathAugmentListEntry : sortedAugmentationsGrouped) {
+            resultCtx = augmentationToGenTypes(basePackageName, schemaPathAugmentListEntry, module, schemaContext,
+                    verboseClassComments, resultCtx, genTypeBuilders, typeProvider);
+
+            for (AugmentationSchemaNode augSchema : schemaPathAugmentListEntry.getValue()) {
+                processUsesImplements(augSchema, module, schemaContext, genCtx, BindingNamespaceType.Data);
+            }
+
         }
+
         return resultCtx;
     }
 
@@ -119,17 +162,26 @@ final class AugmentToGenType {
      * @throws IllegalStateException
      *             if set of module augmentations is null
      */
-    private static List<AugmentationSchema> resolveAugmentations(final Module module) {
+    @VisibleForTesting
+    static List<AugmentationSchemaNode> resolveAugmentations(final Module module,
+            final SchemaContext schemaContext) {
         Preconditions.checkArgument(module != null, "Module reference cannot be NULL.");
         Preconditions.checkState(module.getAugmentations() != null, "Augmentations Set cannot be NULL.");
 
-        final Set<AugmentationSchema> augmentations = module.getAugmentations();
-        final List<AugmentationSchema> sortedAugmentations = new ArrayList<>(augmentations);
-        Collections.sort(sortedAugmentations, AUGMENT_COMP);
-
+        final List<AugmentationSchemaNode> sortedAugmentations = module.getAugmentations().stream()
+                .filter(aug -> !module.equals(findAugmentTargetModule(schemaContext, aug)))
+                .collect(Collectors.toList());
+        sortedAugmentations.sort(AUGMENT_COMP);
         return sortedAugmentations;
     }
 
+    public static Module findAugmentTargetModule(final SchemaContext schemaContext,
+            final AugmentationSchemaNode aug) {
+        Preconditions.checkNotNull(aug, "Augmentation schema can not be null.");
+        final QName first = aug.getTargetPath().getPathFromRoot().iterator().next();
+        return schemaContext.findModule(first.getModule()).orElse(null);
+    }
+
     /**
      * Converts <code>augSchema</code> to list of <code>Type</code> which
      * contains generated type for augmentation. In addition there are also
@@ -137,93 +189,40 @@ final class AugmentToGenType {
      * <code>augSchema</code> node or a generated types for cases are added if
      * augmented node is choice.
      *
-     * @param augmentPackageName
+     * @param basePackageName
      *            string with the name of the package to which the augmentation
      *            belongs
-     * @param augSchema
-     *            AugmentationSchema which is contains data about augmentation
-     *            (target path, childs...)
-     * @param module
-     *            current module
-     * @param schemaContext
-     * @param genCtx
-     * @param genTypeBuilders
+     * @param schemaPathAugmentListEntry
+     *            list of AugmentationSchema nodes grouped by target path
+     * @param module current module
+     * @param schemaContext actual schema context
+     * @param verboseClassComments verbosity switch
+     * @param genCtx generated input context
+     * @param genTypeBuilders auxiliary type builders map
+     * @param typeProvider actual type provider instance
      * @throws IllegalArgumentException
-     *             <ul>
-     *             <li>if <code>augmentPackageName</code> equals null</li>
-     *             <li>if <code>augSchema</code> equals null</li>
-     *             </ul>
+     *             if <code>augmentPackageName</code> equals null
      * @throws IllegalStateException
      *             if augment target path is null
-     * @return
+     * @return generated context
      */
-    private static Map<Module, ModuleContext> augmentationToGenTypes(final String augmentPackageName, final AugmentationSchema augSchema,
-            final Module module, final SchemaContext schemaContext, final boolean verboseClassComments,
-            Map<Module, ModuleContext> genCtx, Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders,
+    @VisibleForTesting
+    static Map<Module, ModuleContext> augmentationToGenTypes(final String basePackageName,
+            final Entry<SchemaPath, List<AugmentationSchemaNode>> schemaPathAugmentListEntry, final Module module,
+            final SchemaContext schemaContext, final boolean verboseClassComments,
+            Map<Module, ModuleContext> genCtx, final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders,
             final TypeProvider typeProvider) {
+        Preconditions.checkArgument(basePackageName != null, "Package Name cannot be NULL.");
+        Preconditions.checkArgument(schemaPathAugmentListEntry != null, "Augmentation List Entry cannot be NULL.");
+        final SchemaPath targetPath = schemaPathAugmentListEntry.getKey();
+        Preconditions.checkState(targetPath != null,
+                "Augmentation List Entry does not contain Target Path (Target Path is NULL).");
 
-        Map<Module, ModuleContext> generatedCtx;
-        Preconditions.checkArgument(augmentPackageName != null, "Package Name cannot be NULL.");
-        Preconditions.checkArgument(augSchema != null, "Augmentation Schema cannot be NULL.");
-        Preconditions.checkState(augSchema.getTargetPath() != null,
-                "Augmentation Schema does not contain Target Path (Target Path is NULL).");
-
-        generatedCtx = GenHelperUtil.processUsesAugments(schemaContext, augSchema, module, genCtx, genTypeBuilders,
-                verboseClassComments, typeProvider);
-        final SchemaPath targetPath = augSchema.getTargetPath();
-        SchemaNode targetSchemaNode;
-
-        targetSchemaNode = SchemaContextUtil.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 in augmentation " + augSchema
-                        + " in module " + module.getName());
-            }
-        }
-        if (targetSchemaNode == null) {
-            throw new IllegalArgumentException("augment target not found: " + targetPath);
-        }
-
-        GeneratedTypeBuilder targetTypeBuilder = GenHelperUtil.findChildNodeByPath(targetSchemaNode.getPath(),
-                generatedCtx);
-        if (targetTypeBuilder == null) {
-            targetTypeBuilder = GenHelperUtil.findCaseByPath(targetSchemaNode.getPath(), generatedCtx);
-        }
-        if (targetTypeBuilder == null) {
-            throw new NullPointerException("Target type not yet generated: " + targetSchemaNode);
-        }
-
-        if (!(targetSchemaNode instanceof ChoiceSchemaNode)) {
-            final String packageName = augmentPackageName;
-            generatedCtx = GenHelperUtil.addRawAugmentGenTypeDefinition(module, packageName, augmentPackageName,
-                    targetTypeBuilder.toInstance(),augSchema, genTypeBuilders, generatedCtx, schemaContext,
-                    verboseClassComments, typeProvider);
-            return generatedCtx;
-
-        } else {
-            generatedCtx = generateTypesFromAugmentedChoiceCases(schemaContext, module, augmentPackageName,
-                    targetTypeBuilder.toInstance(), (ChoiceSchemaNode) targetSchemaNode, augSchema.getChildNodes(),
-                    null, generatedCtx, verboseClassComments, genTypeBuilders, typeProvider);
-            return generatedCtx;
-        }
-    }
-
-    public static Map<Module, ModuleContext> usesAugmentationToGenTypes(final SchemaContext schemaContext, final String
-                        augmentPackageName, final AugmentationSchema augSchema, final Module module, final UsesNode usesNode, final DataNodeContainer
-                        usesNodeParent, Map<Module, ModuleContext> genCtx,
-                        Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders,
-                        final boolean verboseClassComments, final TypeProvider typeProvider) {
-
-        Preconditions.checkArgument(augmentPackageName != null, "Package Name cannot be NULL.");
-        Preconditions.checkArgument(augSchema != null, "Augmentation Schema cannot be NULL.");
-        Preconditions.checkState(augSchema.getTargetPath() != null,
-                "Augmentation Schema does not contain Target Path (Target Path is NULL).");
+        final List<AugmentationSchemaNode> augmentationSchemaList = schemaPathAugmentListEntry.getValue();
+        Preconditions.checkState(!augmentationSchemaList.isEmpty(),
+                "Augmentation List cannot be empty.");
 
-        final SchemaPath targetPath = augSchema.getTargetPath();
-        final SchemaNode targetSchemaNode = findOriginalTargetFromGrouping(schemaContext, targetPath, usesNode);
+        SchemaNode targetSchemaNode = SchemaContextUtil.findDataSchemaNode(schemaContext, targetPath);
         if (targetSchemaNode == null) {
             throw new IllegalArgumentException("augment target not found: " + targetPath);
         }
@@ -237,26 +236,21 @@ final class AugmentToGenType {
             throw new NullPointerException("Target type not yet generated: " + targetSchemaNode);
         }
 
+        final String augmentPackageName =
+            BindingGeneratorUtil.packageNameWithNamespacePrefix(basePackageName, BindingNamespaceType.Data);
+
         if (!(targetSchemaNode instanceof ChoiceSchemaNode)) {
-            String packageName = augmentPackageName;
-            if (usesNodeParent instanceof SchemaNode) {
-                packageName = BindingGeneratorUtil.packageNameForAugmentedGeneratedType(augmentPackageName,
-                        ((SchemaNode) usesNodeParent).getPath());
-            } else if (usesNodeParent instanceof AugmentationSchema) {
-                Type parentTypeBuiler = genCtx.get(module).getTypeToAugmentation().inverse().get(usesNodeParent);
-                packageName = BindingGeneratorUtil.packageNameForAugmentedGeneratedType(
-                        parentTypeBuiler.getPackageName(), (AugmentationSchema)usesNodeParent);
-            }
-            genCtx = GenHelperUtil.addRawAugmentGenTypeDefinition(module, packageName, augmentPackageName,
-                    targetTypeBuilder.toInstance(), augSchema, genTypeBuilders, genCtx, schemaContext,
-                    verboseClassComments, typeProvider);
-            return genCtx;
+            genCtx = GenHelperUtil.addRawAugmentGenTypeDefinition(module, augmentPackageName,
+                targetTypeBuilder, targetSchemaNode, schemaPathAugmentListEntry.getValue(),
+                genTypeBuilders, genCtx, schemaContext, verboseClassComments, typeProvider,
+                targetTypeBuilder.getBindingNamespaceType());
         } else {
-            genCtx = generateTypesFromAugmentedChoiceCases(schemaContext, module, augmentPackageName,
-                    targetTypeBuilder.toInstance(), (ChoiceSchemaNode) targetSchemaNode, augSchema.getChildNodes(),
-                    usesNodeParent, genCtx, verboseClassComments, genTypeBuilders, typeProvider);
-            return genCtx;
+            genCtx = generateTypesFromAugmentedChoiceCases(schemaContext, module, basePackageName,
+                targetTypeBuilder.toInstance(), (ChoiceSchemaNode) targetSchemaNode,
+                schemaPathAugmentListEntry.getValue(),genCtx, verboseClassComments, genTypeBuilders, typeProvider,
+                targetTypeBuilder.getBindingNamespaceType());
         }
+        return genCtx;
     }
 
     /**
@@ -268,19 +262,19 @@ final class AugmentToGenType {
      *            parent of uses node
      * @return node from its original location in grouping
      */
-    private static DataSchemaNode findOriginalTargetFromGrouping(final SchemaContext schemaContext, final SchemaPath targetPath,
-                                          final UsesNode parentUsesNode) {
+    @VisibleForTesting
+    static DataSchemaNode findOriginalTargetFromGrouping(final SchemaContext schemaContext,
+            final SchemaPath targetPath, final UsesNode parentUsesNode) {
         SchemaNode targetGrouping = null;
         QName current = parentUsesNode.getGroupingPath().getPathFromRoot().iterator().next();
-        Module module = schemaContext.findModuleByNamespaceAndRevision(current.getNamespace(), current.getRevision());
+        Module module = schemaContext.findModule(current.getModule()).orElse(null);
         if (module == null) {
             throw new IllegalArgumentException("Fialed to find module for grouping in: " + parentUsesNode);
-        } else {
-            for (GroupingDefinition group : module.getGroupings()) {
-                if (group.getQName().equals(current)) {
-                    targetGrouping = group;
-                    break;
-                }
+        }
+        for (GroupingDefinition group : module.getGroupings()) {
+            if (group.getQName().equals(current)) {
+                targetGrouping = group;
+                break;
             }
         }
 
@@ -288,14 +282,13 @@ final class AugmentToGenType {
             throw new IllegalArgumentException("Failed to generate code for augment in " + parentUsesNode);
         }
 
-        final GroupingDefinition grouping = (GroupingDefinition) targetGrouping;
-        SchemaNode result = grouping;
+        SchemaNode result = targetGrouping;
         for (final QName node : targetPath.getPathFromRoot()) {
             if (result instanceof DataNodeContainer) {
                 final QName resultNode = QName.create(result.getQName().getModule(), node.getLocalName());
                 result = ((DataNodeContainer) result).getDataChildByName(resultNode);
             } else if (result instanceof ChoiceSchemaNode) {
-                result = ((ChoiceSchemaNode) result).getCaseNodeByName(node.getLocalName());
+                result = findNamedCase((ChoiceSchemaNode) result, node.getLocalName());
             }
         }
         if (result == null) {
@@ -346,9 +339,8 @@ final class AugmentToGenType {
      *            Type which represents target choice
      * @param targetNode
      *            node which represents target choice
-     * @param augmentedNodes
-     *            set of choice case nodes for which is checked if are/aren't
-     *            added to choice through augmentation
+     * @param schemaPathAugmentListEntry
+     *            list of AugmentationSchema nodes grouped by target path
      * @return list of generated types which represents augmented cases of
      *         choice <code>refChoiceType</code>
      * @throws IllegalArgumentException
@@ -358,67 +350,57 @@ final class AugmentToGenType {
      *             <li>if <code>augmentedNodes</code> is null</li>
      *             </ul>
      */
-    private static Map<Module, ModuleContext> generateTypesFromAugmentedChoiceCases(final SchemaContext schemaContext, final Module module,
-                          final String basePackageName, final Type targetType, final ChoiceSchemaNode targetNode,
-                          final Iterable<DataSchemaNode> augmentedNodes, final DataNodeContainer usesNodeParent,
-                          Map<Module, ModuleContext> genCtx, final boolean verboseClassComments,
-                          Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders, final TypeProvider typeProvider) {
+    @VisibleForTesting
+    static Map<Module, ModuleContext> generateTypesFromAugmentedChoiceCases(
+            final SchemaContext schemaContext, final Module module,
+            final String basePackageName, final GeneratedType targetType, final ChoiceSchemaNode targetNode,
+            final List<AugmentationSchemaNode> schemaPathAugmentListEntry,
+            final Map<Module, ModuleContext> genCtx, final boolean verboseClassComments,
+            final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders, final TypeProvider typeProvider,
+            final BindingNamespaceType namespaceType) {
         Preconditions.checkArgument(basePackageName != null, "Base Package Name cannot be NULL.");
         Preconditions.checkArgument(targetType != null, "Referenced Choice Type cannot be NULL.");
-        Preconditions.checkArgument(augmentedNodes != null, "Set of Choice Case Nodes cannot be NULL.");
-
-        for (final DataSchemaNode caseNode : augmentedNodes) {
-            if (caseNode != null) {
-                final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName,
-                        caseNode.getPath(), null);
-                final GeneratedTypeBuilder caseTypeBuilder = GenHelperUtil.addDefaultInterfaceDefinition(packageName,
-                        caseNode, module, genCtx, schemaContext, verboseClassComments, genTypeBuilders, typeProvider);
-                caseTypeBuilder.addImplementsType(targetType);
-
-                SchemaNode parent;
-                final SchemaPath nodeSp = targetNode.getPath();
-                parent = SchemaContextUtil.findDataSchemaNode(schemaContext, nodeSp.getParent());
-
-                GeneratedTypeBuilder childOfType = null;
-                if (parent instanceof Module) {
-                    childOfType = genCtx.get(parent).getModuleNode();
-                } else if (parent instanceof ChoiceCaseNode) {
-                    childOfType = GenHelperUtil.findCaseByPath(parent.getPath(), genCtx);
-                } else if (parent instanceof DataSchemaNode || parent instanceof NotificationDefinition) {
-                    childOfType = GenHelperUtil.findChildNodeByPath(parent.getPath(), genCtx);
-                } else if (parent instanceof GroupingDefinition) {
-                    childOfType = GenHelperUtil.findGroupingByPath(parent.getPath(), genCtx);
-                }
-
-                if (childOfType == null) {
-                    throw new IllegalArgumentException("Failed to find parent type of choice " + targetNode);
-                }
-
-                ChoiceCaseNode node = null;
-                final String caseLocalName = caseNode.getQName().getLocalName();
-                if (caseNode instanceof ChoiceCaseNode) {
-                    node = (ChoiceCaseNode) caseNode;
-                } else if (targetNode.getCaseNodeByName(caseLocalName) == null) {
-                    final String targetNodeLocalName = targetNode.getQName().getLocalName();
-                    for (DataSchemaNode dataSchemaNode : usesNodeParent.getChildNodes()) {
-                        if (dataSchemaNode instanceof ChoiceSchemaNode && targetNodeLocalName.equals(dataSchemaNode.getQName
-                                ().getLocalName())) {
-                            node = ((ChoiceSchemaNode) dataSchemaNode).getCaseNodeByName(caseLocalName);
-                            break;
+        Preconditions.checkArgument(schemaPathAugmentListEntry != null, "Set of Choice Case Nodes cannot be NULL.");
+
+
+        for (final AugmentationSchemaNode augmentationSchema : schemaPathAugmentListEntry) {
+            for (final DataSchemaNode childNode : augmentationSchema.getChildNodes()) {
+                if (childNode != null) {
+                    final GeneratedTypeBuilder caseTypeBuilder =
+                        GenHelperUtil.addDefaultInterfaceDefinition(basePackageName, childNode, null, module,
+                            genCtx, schemaContext, verboseClassComments, genTypeBuilders, typeProvider, namespaceType);
+                    caseTypeBuilder.addImplementsType(targetType);
+                    caseTypeBuilder.setParentTypeForBuilder(targetType.getParentTypeForBuilder());
+
+                    //Since uses augment nodes has been processed as inline nodes,
+                    //we just take two situations below.
+                    final CaseSchemaNode caseNode;
+                    if (childNode instanceof CaseSchemaNode) {
+                        caseNode = (CaseSchemaNode) childNode;
+                    } else {
+                        caseNode = findNamedCase(targetNode, childNode.getQName().getLocalName());
+                        if (caseNode == null) {
+                            throw new IllegalArgumentException("Failed to find case node " + childNode);
                         }
                     }
-                } else {
-                    node = targetNode.getCaseNodeByName(caseLocalName);
-                }
-                final Iterable<DataSchemaNode> childNodes = node.getChildNodes();
-                if (childNodes != null) {
-                    GenHelperUtil.resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, childOfType,
-                            childNodes, genCtx, schemaContext, verboseClassComments, genTypeBuilders, typeProvider);
+
+                    final Collection<DataSchemaNode> childNodes = caseNode.getChildNodes();
+                    if (!childNodes.isEmpty()) {
+                        GenHelperUtil.resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder,
+                                (GeneratedTypeBuilder) targetType.getParentTypeForBuilder(),  childNodes, genCtx,
+                            schemaContext, verboseClassComments, genTypeBuilders, typeProvider, namespaceType);
+                        processUsesImplements(caseNode, module, schemaContext, genCtx, namespaceType);
+                    }
+                    genCtx.get(module).addCaseType(childNode.getPath(), caseTypeBuilder);
+                    genCtx.get(module).addChoiceToCaseMapping(targetType, caseTypeBuilder, caseNode);
                 }
-                genCtx.get(module).addCaseType(caseNode.getPath(), caseTypeBuilder);
-                genCtx.get(module).addChoiceToCaseMapping(targetType, caseTypeBuilder, node);
             }
         }
         return genCtx;
     }
+
+    private static CaseSchemaNode findNamedCase(final ChoiceSchemaNode choice, final String caseName) {
+        final List<CaseSchemaNode> cases = choice.findCaseNodes(caseName);
+        return cases.isEmpty() ? null : cases.get(0);
+    }
 }