Bug 2528 - Binding Generator: Generated notification implements ChildOf
[yangtools.git] / code-generator / binding-generator-impl / src / main / java / org / opendaylight / yangtools / sal / binding / generator / impl / BindingGeneratorImpl.java
index 00abec0db68d4006ec7561bf4b9174ddd66ee7ab..c8db5f1ebc2b76a627df951d8b986b466f8b255c 100644 (file)
@@ -12,7 +12,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkState;
 import static org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil.computeDefaultSUID;
 import static org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil.packageNameForGeneratedType;
-import static org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil.parseToValidParamName;
 import static org.opendaylight.yangtools.binding.generator.util.BindingTypes.DATA_OBJECT;
 import static org.opendaylight.yangtools.binding.generator.util.BindingTypes.DATA_ROOT;
 import static org.opendaylight.yangtools.binding.generator.util.BindingTypes.IDENTIFIABLE;
@@ -26,6 +25,7 @@ import static org.opendaylight.yangtools.binding.generator.util.Types.typeForCla
 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNode;
 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findNodeInSchemaContext;
 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findParentModule;
+import com.google.common.base.Preconditions;
 import com.google.common.base.Splitter;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Sets;
@@ -37,6 +37,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import org.opendaylight.yangtools.sal.binding.generator.impl.YangTemplate;
 import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil;
 import org.opendaylight.yangtools.binding.generator.util.BindingTypes;
 import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl;
@@ -71,7 +72,7 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
-import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+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.DataSchemaNode;
@@ -94,8 +95,10 @@ 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.UnionTypeDefinition;
+import org.opendaylight.yangtools.yang.model.util.BaseTypes;
 import org.opendaylight.yangtools.yang.model.util.DataNodeIterator;
 import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
+import org.opendaylight.yangtools.yang.model.util.SchemaNodeUtils;
 import org.opendaylight.yangtools.yang.model.util.UnionType;
 import org.opendaylight.yangtools.yang.parser.builder.util.Comparators;
 import org.opendaylight.yangtools.yang.parser.util.ModuleDependencySort;
@@ -107,6 +110,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
     private static final Splitter COLON_SPLITTER = Splitter.on(':');
     private static final Splitter BSDOT_SPLITTER = Splitter.on("\\.");
     private static final char NEW_LINE = '\n';
+    private static final String QNAME_FQCN = QName.class.getName();
 
     /**
      * Constant with the concrete name of identifier.
@@ -210,7 +214,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
      *         <ul>
      *         <li>are generated from <code>context</code> schema nodes and</li>
      *         <li>are also part of some of the module in <code>modules</code>
-     *         set</li>.
+     *         set.</li>
      *         </ul>
      * @throws IllegalArgumentException
      *             <ul>
@@ -228,20 +232,20 @@ public class BindingGeneratorImpl implements BindingGenerator {
 
         schemaContext = context;
         typeProvider = new TypeProviderImpl(context);
-        Module[] modulesArray = new Module[context.getModules().size()];
+        final Module[] modulesArray = new Module[context.getModules().size()];
         context.getModules().toArray(modulesArray);
         final List<Module> contextModules = ModuleDependencySort.sort(modulesArray);
         genTypeBuilders = new HashMap<>();
 
-        for (Module contextModule : contextModules) {
+        for (final Module contextModule : contextModules) {
             moduleToGenTypes(contextModule, context);
         }
-        for (Module contextModule : contextModules) {
+        for (final Module contextModule : contextModules) {
             allAugmentsToGenTypes(contextModule);
         }
 
         final List<Type> filteredGenTypes = new ArrayList<>();
-        for (Module m : modules) {
+        for (final Module m : modules) {
             final ModuleContext ctx = checkNotNull(genCtx.get(m), "Module context not found for module %s", m);
             filteredGenTypes.addAll(ctx.getGeneratedTypes());
             final Set<Type> additionalTypes = ((TypeProviderImpl) typeProvider).getAdditionalTypes().get(m);
@@ -290,7 +294,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
         final List<TypeDefinition<?>> typeDefinitions = it.allTypedefs();
         checkState(typeDefinitions != null, "Type Definitions for module «module.name» cannot be NULL.");
 
-        for (TypeDefinition<?> typedef : typeDefinitions) {
+        for (final TypeDefinition<?> typedef : typeDefinitions) {
             if (typedef != null) {
                 final Type type = ((TypeProviderImpl) typeProvider).generatedTypeForExtendedDefinitionType(typedef,
                         typedef);
@@ -348,7 +352,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
                 genType.addImplementsType(identifiableMarker);
             }
 
-            for (DataSchemaNode schemaNode : node.getChildNodes()) {
+            for (final DataSchemaNode schemaNode : node.getChildNodes()) {
                 if (!schemaNode.isAugmenting()) {
                     addSchemaNodeToListBuilders(basePackageName, schemaNode, genType, genTOBuilder, listKeys, module);
                 }
@@ -367,8 +371,8 @@ public class BindingGeneratorImpl implements BindingGenerator {
 
     private void processUsesAugments(final DataNodeContainer node, final Module module) {
         final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
-        for (UsesNode usesNode : node.getUses()) {
-            for (AugmentationSchema augment : usesNode.getAugmentations()) {
+        for (final UsesNode usesNode : node.getUses()) {
+            for (final AugmentationSchema augment : usesNode.getAugmentations()) {
                 usesAugmentationToGenTypes(basePackageName, augment, module, usesNode, node);
                 processUsesAugments(augment, module);
             }
@@ -397,7 +401,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
 
         final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
         final List<AugmentationSchema> augmentations = resolveAugmentations(module);
-        for (AugmentationSchema augment : augmentations) {
+        for (final AugmentationSchema augment : augmentations) {
             augmentationToGenTypes(basePackageName, augment, module);
         }
     }
@@ -421,7 +425,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
         checkState(module.getAugmentations() != null, "Augmentations Set cannot be NULL.");
 
         final Set<AugmentationSchema> augmentations = module.getAugmentations();
-        List<AugmentationSchema> sortedAugmentations = new ArrayList<>(augmentations);
+        final List<AugmentationSchema> sortedAugmentations = new ArrayList<>(augmentations);
         Collections.sort(sortedAugmentations, Comparators.AUGMENT_COMP);
 
         return sortedAugmentations;
@@ -479,10 +483,10 @@ public class BindingGeneratorImpl implements BindingGenerator {
         interfaceBuilder.addImplementsType(Types.typeForClass(RpcService.class));
         interfaceBuilder.setDescription(createDescription(rpcDefinitions, module.getName(), module.getModuleSourcePath()));
 
-        for (RpcDefinition rpc : rpcDefinitions) {
+        for (final RpcDefinition rpc : rpcDefinitions) {
             if (rpc != null) {
                 final String rpcName = BindingMapping.getClassName(rpc.getQName());
-                final String rpcMethodName = parseToValidParamName(rpcName);
+                final String rpcMethodName = BindingMapping.getPropertyName(rpcName);
                 final String rpcComment = rpc.getDescription();
                 final MethodSignatureBuilder method = interfaceBuilder.addMethod(rpcMethodName);
                 final ContainerSchemaNode input = rpc.getInput();
@@ -550,12 +554,12 @@ public class BindingGeneratorImpl implements BindingGenerator {
 
 
 
-        for (NotificationDefinition notification : notifications) {
+        for (final NotificationDefinition notification : notifications) {
             if (notification != null) {
                 processUsesAugments(notification, module);
 
                 final GeneratedTypeBuilder notificationInterface = addDefaultInterfaceDefinition(basePackageName,
-                        notification, BindingTypes.DATA_OBJECT, module);
+                        notification, null, module);
                 notificationInterface.addImplementsType(NOTIFICATION);
                 genCtx.get(module).addChildNodeType(notification, notificationInterface);
 
@@ -590,7 +594,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
         final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
 
         if (schemaIdentities != null && !schemaIdentities.isEmpty()) {
-            for (IdentitySchemaNode identity : schemaIdentities) {
+            for (final IdentitySchemaNode identity : schemaIdentities) {
                 identityToGenType(module, basePackageName, identity, context);
             }
         }
@@ -652,7 +656,9 @@ public class BindingGeneratorImpl implements BindingGenerator {
 
     private static Constant qnameConstant(final GeneratedTypeBuilderBase<?> toBuilder, final String constantName,
             final QName name) {
-        StringBuilder sb = new StringBuilder("org.opendaylight.yangtools.yang.common.QName");
+        final StringBuilder sb = new StringBuilder(QNAME_FQCN);
+        sb.append(".cachedReference(");
+        sb.append(QNAME_FQCN);
         sb.append(".create(");
         sb.append('"');
         sb.append(name.getNamespace());
@@ -660,7 +666,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
         sb.append(name.getFormattedRevision());
         sb.append("\",\"");
         sb.append(name.getLocalName());
-        sb.append("\");");
+        sb.append("\"))");
 
         return toBuilder.addConstant(typeForClass(QName.class), constantName, sb.toString());
     }
@@ -682,7 +688,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
         final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
         final List<GroupingDefinition> groupingsSortedByDependencies = new GroupingDefinitionDependencySort()
         .sort(groupings);
-        for (GroupingDefinition grouping : groupingsSortedByDependencies) {
+        for (final GroupingDefinition grouping : groupingsSortedByDependencies) {
             groupingToGenType(basePackageName, grouping, module);
         }
     }
@@ -724,17 +730,21 @@ public class BindingGeneratorImpl implements BindingGenerator {
      *            builder
      * @param typeBuilder
      *            GeneratedTypeBuilder to which will be enum builder assigned
+     * @param module
+     *            Module in which type should be generated
      * @return enumeration builder which contains data from
      *         <code>enumTypeDef</code>
      */
     private EnumBuilder resolveInnerEnumFromTypeDefinition(final EnumTypeDefinition enumTypeDef, final QName enumName,
-            final GeneratedTypeBuilder typeBuilder) {
+            final GeneratedTypeBuilder typeBuilder, Module module) {
         if ((enumTypeDef != null) && (typeBuilder != null) && (enumTypeDef.getQName() != null)
                 && (enumTypeDef.getQName().getLocalName() != null)) {
             final String enumerationName = BindingMapping.getClassName(enumName);
             final EnumBuilder enumBuilder = typeBuilder.addEnumeration(enumerationName);
             enumBuilder.setDescription(enumTypeDef.getDescription());
             enumBuilder.updateEnumPairsFromEnumTypeDef(enumTypeDef);
+            ModuleContext ctx = genCtx.get(module);
+            ctx.addInnerTypedefType(enumTypeDef.getPath(), enumBuilder);
             return enumBuilder;
         }
         return null;
@@ -824,15 +834,15 @@ public class BindingGeneratorImpl implements BindingGenerator {
             throw new NullPointerException("Target type not yet generated: " + targetSchemaNode);
         }
 
-        if (!(targetSchemaNode instanceof ChoiceNode)) {
-            String packageName = augmentPackageName;
+        if (!(targetSchemaNode instanceof ChoiceSchemaNode)) {
+            final String packageName = augmentPackageName;
             final Type targetType = new ReferencedTypeImpl(targetTypeBuilder.getPackageName(),
                     targetTypeBuilder.getName());
             addRawAugmentGenTypeDefinition(module, packageName, augmentPackageName, targetType, augSchema);
 
         } else {
             generateTypesFromAugmentedChoiceCases(module, augmentPackageName, targetTypeBuilder.toInstance(),
-                    (ChoiceNode) targetSchemaNode, augSchema.getChildNodes());
+                    (ChoiceSchemaNode) targetSchemaNode, augSchema.getChildNodes());
         }
     }
 
@@ -845,7 +855,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
 
         processUsesAugments(augSchema, module);
         final SchemaPath targetPath = augSchema.getTargetPath();
-        SchemaNode targetSchemaNode = findOriginalTargetFromGrouping(targetPath, usesNode);
+        final SchemaNode targetSchemaNode = findOriginalTargetFromGrouping(targetPath, usesNode);
         if (targetSchemaNode == null) {
             throw new IllegalArgumentException("augment target not found: " + targetPath);
         }
@@ -858,7 +868,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
             throw new NullPointerException("Target type not yet generated: " + targetSchemaNode);
         }
 
-        if (!(targetSchemaNode instanceof ChoiceNode)) {
+        if (!(targetSchemaNode instanceof ChoiceSchemaNode)) {
             String packageName = augmentPackageName;
             if (usesNodeParent instanceof SchemaNode) {
                 packageName = packageNameForGeneratedType(augmentPackageName, ((SchemaNode) usesNodeParent).getPath(),
@@ -868,7 +878,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
                     augSchema);
         } else {
             generateTypesFromAugmentedChoiceCases(module, augmentPackageName, targetTypeBuilder.toInstance(),
-                    (ChoiceNode) targetSchemaNode, augSchema.getChildNodes());
+                    (ChoiceSchemaNode) targetSchemaNode, augSchema.getChildNodes());
         }
     }
 
@@ -882,21 +892,21 @@ public class BindingGeneratorImpl implements BindingGenerator {
      * @return node from its original location in grouping
      */
     private DataSchemaNode findOriginalTargetFromGrouping(final SchemaPath targetPath, final UsesNode parentUsesNode) {
-        SchemaNode targetGrouping = findNodeInSchemaContext(schemaContext, parentUsesNode.getGroupingPath()
+        final SchemaNode targetGrouping = findNodeInSchemaContext(schemaContext, parentUsesNode.getGroupingPath()
                 .getPathFromRoot());
         if (!(targetGrouping instanceof GroupingDefinition)) {
             throw new IllegalArgumentException("Failed to generate code for augment in " + parentUsesNode);
         }
 
-        GroupingDefinition grouping = (GroupingDefinition) targetGrouping;
+        final GroupingDefinition grouping = (GroupingDefinition) targetGrouping;
         SchemaNode result = grouping;
-        for (QName node : targetPath.getPathFromRoot()) {
+        for (final QName node : targetPath.getPathFromRoot()) {
             // finding by local name is valid, grouping cannot contain nodes
             // with same name and different namespace
             if (result instanceof DataNodeContainer) {
                 result = ((DataNodeContainer) result).getDataChildByName(node.getLocalName());
-            } else if (result instanceof ChoiceNode) {
-                result = ((ChoiceNode) result).getCaseNodeByName(node.getLocalName());
+            } else if (result instanceof ChoiceSchemaNode) {
+                result = ((ChoiceSchemaNode) result).getCaseNodeByName(node.getLocalName());
             }
         }
         if (result == null) {
@@ -904,7 +914,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
         }
 
         boolean fromUses = ((DataSchemaNode) result).isAddedByUses();
-        Iterator<UsesNode> groupingUses = grouping.getUses().iterator();
+        final Iterator<UsesNode> groupingUses = grouping.getUses().iterator();
         while (groupingUses.hasNext() && fromUses) {
             result = findOriginalTargetFromGrouping(targetPath, groupingUses.next());
             if (result != null) {
@@ -981,7 +991,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
      * @return nodeParameter of UnknownSchemaNode
      */
     private String getAugmentIdentifier(final List<UnknownSchemaNode> unknownSchemaNodes) {
-        for (UnknownSchemaNode unknownSchemaNode : unknownSchemaNodes) {
+        for (final UnknownSchemaNode unknownSchemaNode : unknownSchemaNodes) {
             final QName nodeType = unknownSchemaNode.getNodeType();
             if (AUGMENT_IDENTIFIER_NAME.equals(nodeType.getLocalName())
                     && YANG_EXT_NAMESPACE.equals(nodeType.getNamespace().toString())) {
@@ -1041,7 +1051,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
     private GeneratedTypeBuilder resolveDataSchemaNodes(final Module module, final String basePackageName,
             final GeneratedTypeBuilder parent, final GeneratedTypeBuilder childOf, final Iterable<DataSchemaNode> schemaNodes) {
         if (schemaNodes != null && parent != null) {
-            for (DataSchemaNode schemaNode : schemaNodes) {
+            for (final DataSchemaNode schemaNode : schemaNodes) {
                 if (!schemaNode.isAugmenting() && !schemaNode.isAddedByUses()) {
                     addSchemaNodeToBuilderAsMethod(basePackageName, schemaNode, parent, childOf, module);
                 }
@@ -1076,7 +1086,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
             final GeneratedTypeBuilder typeBuilder, final GeneratedTypeBuilder childOf,
             final Iterable<DataSchemaNode> schemaNodes) {
         if ((schemaNodes != null) && (typeBuilder != null)) {
-            for (DataSchemaNode schemaNode : schemaNodes) {
+            for (final DataSchemaNode schemaNode : schemaNodes) {
                 if (!schemaNode.isAugmenting()) {
                     addSchemaNodeToBuilderAsMethod(basePackageName, schemaNode, typeBuilder, childOf, module);
                 }
@@ -1106,15 +1116,15 @@ public class BindingGeneratorImpl implements BindingGenerator {
             final GeneratedTypeBuilder typeBuilder, final GeneratedTypeBuilder childOf, final Module module) {
         if (node != null && typeBuilder != null) {
             if (node instanceof LeafSchemaNode) {
-                resolveLeafSchemaNodeAsMethod(typeBuilder, (LeafSchemaNode) node);
+                resolveLeafSchemaNodeAsMethod(typeBuilder, (LeafSchemaNode) node, module);
             } else if (node instanceof LeafListSchemaNode) {
-                resolveLeafListSchemaNode(typeBuilder, (LeafListSchemaNode) node);
+                resolveLeafListSchemaNode(typeBuilder, (LeafListSchemaNode) node,module);
             } else if (node instanceof ContainerSchemaNode) {
                 containerToGenType(module, basePackageName, typeBuilder, childOf, (ContainerSchemaNode) node);
             } else if (node instanceof ListSchemaNode) {
                 listToGenType(module, basePackageName, typeBuilder, childOf, (ListSchemaNode) node);
-            } else if (node instanceof ChoiceNode) {
-                choiceToGeneratedType(module, basePackageName, typeBuilder, (ChoiceNode) node);
+            } else if (node instanceof ChoiceSchemaNode) {
+                choiceToGeneratedType(module, basePackageName, typeBuilder, (ChoiceSchemaNode) node);
             } else {
                 // TODO: anyxml not yet supported
                 LOG.debug("Unable to add schema node {} as method in {}: unsupported type of node.", node.getClass(),
@@ -1147,7 +1157,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
      *             </ul>
      */
     private void choiceToGeneratedType(final Module module, final String basePackageName,
-            final GeneratedTypeBuilder parent, final ChoiceNode choiceNode) {
+            final GeneratedTypeBuilder parent, final ChoiceSchemaNode choiceNode) {
         checkArgument(basePackageName != null, "Base Package Name cannot be NULL.");
         checkArgument(choiceNode != null, "Choice Schema Node cannot be NULL.");
 
@@ -1190,7 +1200,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
      *             </ul>
      */
     private void generateTypesFromChoiceCases(final Module module, final String basePackageName,
-            final Type refChoiceType, final ChoiceNode choiceNode) {
+            final Type refChoiceType, final ChoiceSchemaNode choiceNode) {
         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.");
@@ -1200,7 +1210,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
             return;
         }
 
-        for (ChoiceCaseNode caseNode : caseNodes) {
+        for (final ChoiceCaseNode caseNode : caseNodes) {
             if (caseNode != null && !caseNode.isAddedByUses() && !caseNode.isAugmenting()) {
                 final String packageName = packageNameForGeneratedType(basePackageName, caseNode.getPath());
                 final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode, module);
@@ -1209,39 +1219,41 @@ public class BindingGeneratorImpl implements BindingGenerator {
                 genCtx.get(module).addChoiceToCaseMapping(refChoiceType, caseTypeBuilder, caseNode);
                 final Iterable<DataSchemaNode> caseChildNodes = caseNode.getChildNodes();
                 if (caseChildNodes != null) {
-                    Object parentNode = null;
-                    final SchemaPath nodeSp = choiceNode.getPath();
-                    parentNode = findDataSchemaNode(schemaContext, nodeSp.getParent());
-
-                    SchemaNode parent;
-                    if (parentNode instanceof AugmentationSchema) {
-                        final AugmentationSchema augSchema = (AugmentationSchema) parentNode;
-                        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());
+                    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;
                         }
-                        parent = targetSchemaNode;
-                    } else {
-                        final SchemaPath sp = choiceNode.getPath();
-                        parent = findDataSchemaNode(schemaContext, sp.getParent());
-                    }
-                    GeneratedTypeBuilder childOfType = findChildNodeByPath(parent.getPath());
-                    if (childOfType == null) {
-                        childOfType = findGroupingByPath(parent.getPath());
-                    }
-                    resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, childOfType, caseChildNodes);
-                }
-            }
 
+                        Preconditions.checkState(parent != null, "Could not find Choice node parent %s",
+                                choiceNodeParentPath);
+                        GeneratedTypeBuilder childOfType = findChildNodeByPath(parent.getPath());
+                        if (childOfType == null) {
+                            childOfType = findGroupingByPath(parent.getPath());
+                        }
+                        resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, childOfType, caseChildNodes);
+                    } else
+                        resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, moduleToDataType(module),
+                                caseChildNodes);
+               }
+            }
             processUsesAugments(caseNode, module);
         }
     }
@@ -1274,12 +1286,12 @@ public class BindingGeneratorImpl implements BindingGenerator {
      *             </ul>
      */
     private void generateTypesFromAugmentedChoiceCases(final Module module, final String basePackageName,
-            final Type targetType, final ChoiceNode targetNode, final Iterable<DataSchemaNode> augmentedNodes) {
+            final Type targetType, final ChoiceSchemaNode targetNode, final Iterable<DataSchemaNode> augmentedNodes) {
         checkArgument(basePackageName != null, "Base Package Name cannot be NULL.");
         checkArgument(targetType != null, "Referenced Choice Type cannot be NULL.");
         checkArgument(augmentedNodes != null, "Set of Choice Case Nodes cannot be NULL.");
 
-        for (DataSchemaNode caseNode : augmentedNodes) {
+        for (final DataSchemaNode caseNode : augmentedNodes) {
             if (caseNode != null) {
                 final String packageName = packageNameForGeneratedType(basePackageName, caseNode.getPath());
                 final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode, module);
@@ -1330,6 +1342,8 @@ public class BindingGeneratorImpl implements BindingGenerator {
      * @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
      *         <ul>
      *         <li>false - if <code>leaf</code> or <code>typeBuilder</code> are
@@ -1337,7 +1351,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
      *         <li>true - in other cases</li>
      *         </ul>
      */
-    private Type resolveLeafSchemaNodeAsMethod(final GeneratedTypeBuilder typeBuilder, final LeafSchemaNode leaf) {
+    private Type resolveLeafSchemaNodeAsMethod(final GeneratedTypeBuilder typeBuilder, final LeafSchemaNode leaf, Module module) {
         Type returnType = null;
         if ((leaf != null) && (typeBuilder != null)) {
             final String leafName = leaf.getQName().getLocalName();
@@ -1355,7 +1369,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
                     returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf);
                     final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) typeDef;
                     final EnumBuilder enumBuilder = resolveInnerEnumFromTypeDefinition(enumTypeDef, leaf.getQName(),
-                            typeBuilder);
+                            typeBuilder,module);
 
                     if (enumBuilder != null) {
                         returnType = enumBuilder.toInstance(typeBuilder);
@@ -1386,7 +1400,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
 
     private void processContextRefExtension(final LeafSchemaNode leaf, final MethodSignatureBuilder getter,
             final Module module) {
-        for (UnknownSchemaNode node : leaf.getUnknownSchemaNodes()) {
+        for (final UnknownSchemaNode node : leaf.getUnknownSchemaNodes()) {
             final QName nodeType = node.getNodeType();
             if ("context-reference".equals(nodeType.getLocalName())) {
                 final String nodeParam = node.getNodeParameter();
@@ -1399,7 +1413,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
                     identity = findIdentityByName(module.getIdentities(), iterator.next());
                     basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
                 } else if (length == 2) {
-                    String prefix = iterator.next();
+                    final String prefix = iterator.next();
                     final Module dependentModule = findModuleFromImports(module.getImports(), prefix);
                     if (dependentModule == null) {
                         throw new IllegalArgumentException("Failed to process context-reference: unknown prefix "
@@ -1427,7 +1441,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
     }
 
     private IdentitySchemaNode findIdentityByName(final Set<IdentitySchemaNode> identities, final String name) {
-        for (IdentitySchemaNode id : identities) {
+        for (final IdentitySchemaNode id : identities) {
             if (id.getQName().getLocalName().equals(name)) {
                 return id;
             }
@@ -1436,7 +1450,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
     }
 
     private Module findModuleFromImports(final Set<ModuleImport> imports, final String prefix) {
-        for (ModuleImport imp : imports) {
+        for (final ModuleImport imp : imports) {
             if (imp.getPrefix().equals(prefix)) {
                 return schemaContext.findModuleByName(imp.getModuleName(), imp.getRevision());
             }
@@ -1452,23 +1466,27 @@ public class BindingGeneratorImpl implements BindingGenerator {
             if (leafDesc == null) {
                 leafDesc = "";
             }
-
-            if (leafName != null) {
-                Type returnType = null;
-                final TypeDefinition<?> typeDef = leaf.getType();
-                if (typeDef instanceof UnionTypeDefinition) {
-                    // GeneratedType for this type definition should be already
-                    // created
-                    QName qname = typeDef.getQName();
-                    Module unionModule = schemaContext.findModuleByNamespaceAndRevision(qname.getNamespace(),
-                            qname.getRevision());
-                    final ModuleContext mc = genCtx.get(unionModule);
-                    returnType = mc.getTypedefs().get(typeDef.getPath());
-                } else {
-                    returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf);
-                }
-                return resolveLeafSchemaNodeAsProperty(toBuilder, leaf, returnType, isReadOnly);
+            Type returnType = null;
+            final TypeDefinition<?> typeDef = leaf.getType();
+            if (typeDef instanceof UnionTypeDefinition) {
+                // GeneratedType for this type definition should be already
+                // created
+                final QName qname = typeDef.getQName();
+                final Module unionModule = schemaContext.findModuleByNamespaceAndRevision(qname.getNamespace(),
+                        qname.getRevision());
+                final ModuleContext mc = genCtx.get(unionModule);
+                returnType = mc.getTypedefs().get(typeDef.getPath());
+            } else if (typeDef instanceof EnumTypeDefinition && BaseTypes.ENUMERATION_QNAME.equals(typeDef.getQName())) {
+                // 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());
+                returnType = genCtx.get(enumModule).getInnerType(originalLeaf.getType().getPath());
+            } else {
+                returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf);
             }
+            return resolveLeafSchemaNodeAsProperty(toBuilder, leaf, returnType, isReadOnly);
         }
         return false;
     }
@@ -1501,7 +1519,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
         }
         final String leafName = leaf.getQName().getLocalName();
         final String leafDesc = leaf.getDescription();
-        final GeneratedPropertyBuilder propBuilder = toBuilder.addProperty(parseToValidParamName(leafName));
+        final GeneratedPropertyBuilder propBuilder = toBuilder.addProperty(BindingMapping.getPropertyName(leafName));
         propBuilder.setReadOnly(isReadOnly);
         propBuilder.setReturnType(returnType);
         propBuilder.setComment(leafDesc);
@@ -1521,6 +1539,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
      * @param node
      *            leaf list schema node which is added to
      *            <code>typeBuilder</code> as getter method
+     * @param module
      * @return boolean value
      *         <ul>
      *         <li>true - if <code>node</code>, <code>typeBuilder</code>,
@@ -1528,7 +1547,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
      *         <li>false - other cases</li>
      *         </ul>
      */
-    private boolean resolveLeafListSchemaNode(final GeneratedTypeBuilder typeBuilder, final LeafListSchemaNode node) {
+    private boolean resolveLeafListSchemaNode(final GeneratedTypeBuilder typeBuilder, final LeafListSchemaNode node, Module module) {
         if ((node != null) && (typeBuilder != null)) {
             final QName nodeName = node.getQName();
 
@@ -1541,7 +1560,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
                     returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, node);
                     final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) typeDef;
                     final EnumBuilder enumBuilder = resolveInnerEnumFromTypeDefinition(enumTypeDef, nodeName,
-                            typeBuilder);
+                            typeBuilder,module);
                     returnType = new ReferencedTypeImpl(enumBuilder.getPackageName(), enumBuilder.getName());
                     ((TypeProviderImpl) typeProvider).putReferencedType(node.getPath(), returnType);
                 } else if (typeDef instanceof UnionType) {
@@ -1579,10 +1598,11 @@ public class BindingGeneratorImpl implements BindingGenerator {
         genTOBuilder.setIsUnion(true);
         ((TypeProviderImpl) typeProvider).addUnitsToGenTO(genTOBuilder, typeDef.getUnits());
 
-        // union builder
-        final GeneratedTOBuilder unionBuilder = new GeneratedTOBuilderImpl(typeBuilder.getPackageName(),
-                genTOBuilder.getName() + "Builder");
-        unionBuilder.setIsUnionBuilder(true);
+
+
+        final GeneratedTOBuilder unionBuilder = createUnionBuilder(genTOBuilder,typeBuilder);
+
+
         final MethodSignatureBuilder method = unionBuilder.addMethod("getDefaultInstance");
         method.setReturnType(returnType);
         method.addParameter(Types.STRING, "defaultValue");
@@ -1599,6 +1619,22 @@ public class BindingGeneratorImpl implements BindingGenerator {
         return returnType.toInstance();
     }
 
+    private GeneratedTOBuilder createUnionBuilder(final GeneratedTOBuilder genTOBuilder, final GeneratedTypeBuilder typeBuilder) {
+
+        final String outerCls = Types.getOuterClassName(genTOBuilder);
+        final StringBuilder name;
+        if(outerCls != null) {
+            name = new StringBuilder(outerCls);
+        } else {
+            name = new StringBuilder();
+        }
+        name.append(genTOBuilder.getName());
+        name.append("Builder");
+        final GeneratedTOBuilderImpl unionBuilder = new GeneratedTOBuilderImpl(typeBuilder.getPackageName(),name.toString());
+        unionBuilder.setIsUnionBuilder(true);
+        return unionBuilder;
+    }
+
     private GeneratedTypeBuilder addDefaultInterfaceDefinition(final String packageName, final SchemaNode schemaNode,
             final Module module) {
         return addDefaultInterfaceDefinition(packageName, schemaNode, null, module);
@@ -1609,10 +1645,10 @@ public class BindingGeneratorImpl implements BindingGenerator {
      * <code>schemaNode</code>.
      *
      * The new builder always implements
-     * {@link org.opendaylight.yangtools.yang.binding.DataObject DataObject}.<br />
+     * {@link org.opendaylight.yangtools.yang.binding.DataObject DataObject}.<br>
      * If <code>schemaNode</code> is instance of GroupingDefinition it also
      * implements {@link org.opendaylight.yangtools.yang.binding.Augmentable
-     * Augmentable}.<br />
+     * Augmentable}.<br>
      * If <code>schemaNode</code> is instance of
      * {@link org.opendaylight.yangtools.yang.model.api.DataNodeContainer
      * DataNodeContainer} it can also implement nodes which are specified in
@@ -1741,7 +1777,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
         } else {
             method.append("get");
         }
-        String name = BindingMapping.toFirstUpper(BindingMapping.getPropertyName(localName));
+        final String name = BindingMapping.toFirstUpper(BindingMapping.getPropertyName(localName));
         method.append(name);
         return method.toString();
     }
@@ -1809,7 +1845,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
         if (schemaNode instanceof LeafSchemaNode) {
             final LeafSchemaNode leaf = (LeafSchemaNode) schemaNode;
             final String leafName = leaf.getQName().getLocalName();
-            final Type type = resolveLeafSchemaNodeAsMethod(typeBuilder, leaf);
+            final Type type = resolveLeafSchemaNodeAsMethod(typeBuilder, leaf,module);
             if (listKeys.contains(leafName)) {
                 if (type == null) {
                     resolveLeafSchemaNodeAsProperty(genTOBuilder, leaf, true, module);
@@ -1819,11 +1855,11 @@ public class BindingGeneratorImpl implements BindingGenerator {
             }
         } else if (!schemaNode.isAddedByUses()) {
             if (schemaNode instanceof LeafListSchemaNode) {
-                resolveLeafListSchemaNode(typeBuilder, (LeafListSchemaNode) schemaNode);
+                resolveLeafListSchemaNode(typeBuilder, (LeafListSchemaNode) schemaNode, module);
             } else if (schemaNode instanceof ContainerSchemaNode) {
                 containerToGenType(module, basePackageName, typeBuilder, typeBuilder, (ContainerSchemaNode) schemaNode);
-            } else if (schemaNode instanceof ChoiceNode) {
-                choiceToGeneratedType(module, basePackageName, typeBuilder, (ChoiceNode) schemaNode);
+            } else if (schemaNode instanceof ChoiceSchemaNode) {
+                choiceToGeneratedType(module, basePackageName, typeBuilder, (ChoiceSchemaNode) schemaNode);
             } else if (schemaNode instanceof ListSchemaNode) {
                 listToGenType(module, basePackageName, typeBuilder, typeBuilder, (ListSchemaNode) schemaNode);
             }
@@ -1835,7 +1871,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
         checkArgument(typeBuilder != null, "Generated Type Builder cannot be NULL.");
 
         if (genTOBuilder != null) {
-            GeneratedTransferObject genTO = genTOBuilder.toInstance();
+            final GeneratedTransferObject genTO = genTOBuilder.toInstance();
             constructGetter(typeBuilder, "key", "Returns Primary Key of Yang List Type", genTO);
             genCtx.get(module).addGeneratedTOBuilder(genTOBuilder);
         }
@@ -1854,9 +1890,9 @@ public class BindingGeneratorImpl implements BindingGenerator {
     private List<String> listKeys(final ListSchemaNode list) {
         final List<String> listKeys = new ArrayList<>();
 
-        List<QName> keyDefinition = list.getKeyDefinition();
+        final List<QName> keyDefinition = list.getKeyDefinition();
         if (keyDefinition != null) {
-            for (QName keyDef : keyDefinition) {
+            for (final QName keyDef : keyDefinition) {
                 listKeys.add(keyDef.getLocalName());
             }
         }
@@ -1923,7 +1959,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
                 throw new IllegalStateException("No GeneratedTOBuilder objects generated from union " + typeDef);
             }
             resultTOBuilder = types.remove(0);
-            for (GeneratedTOBuilder genTOBuilder : types) {
+            for (final GeneratedTOBuilder genTOBuilder : types) {
                 resultTOBuilder.addEnclosingTransferObject(genTOBuilder);
             }
 
@@ -1938,7 +1974,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
                     packageName, typeDef, classNameFromLeaf, parentModule.getName()));
         }
         if (genTOBuilders != null && !genTOBuilders.isEmpty()) {
-            for (GeneratedTOBuilder genTOBuilder : genTOBuilders) {
+            for (final GeneratedTOBuilder genTOBuilder : genTOBuilders) {
                 typeBuilder.addEnclosingTransferObject(genTOBuilder);
             }
             return genTOBuilders.get(0);
@@ -1965,7 +2001,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
      */
     private GeneratedTypeBuilder addImplementedInterfaceFromUses(final DataNodeContainer dataNodeContainer,
             final GeneratedTypeBuilder builder) {
-        for (UsesNode usesNode : dataNodeContainer.getUses()) {
+        for (final UsesNode usesNode : dataNodeContainer.getUses()) {
             if (usesNode.getGroupingPath() != null) {
                 final GeneratedType genType = findGroupingByPath(usesNode.getGroupingPath()).toInstance();
                 if (genType == null) {
@@ -2003,7 +2039,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
             }
         }
         sb.append(NEW_LINE);
-        sb.append("<br />(Source path: <i>");
+        sb.append("<br>(Source path: <i>");
         sb.append(moduleSourcePath);
         sb.append("</i>):");
         sb.append(NEW_LINE);
@@ -2031,18 +2067,12 @@ public class BindingGeneratorImpl implements BindingGenerator {
         if (verboseClassComments) {
             final Module module = findParentModule(schemaContext, schemaNode);
             final StringBuilder linkToBuilderClass = new StringBuilder();
-            final StringBuilder linkToKeyClass = new StringBuilder();
             final String[] namespace = Iterables.toArray(BSDOT_SPLITTER.split(fullyQualifiedName), String.class);
-            String className = namespace[namespace.length - 1];
+            final String className = namespace[namespace.length - 1];
 
             if (hasBuilderClass(schemaNode)) {
                 linkToBuilderClass.append(className);
                 linkToBuilderClass.append("Builder");
-
-                if (schemaNode instanceof ListSchemaNode) {
-                    linkToKeyClass.append(className);
-                    linkToKeyClass.append("Key");
-                }
             }
 
             sb.append("<p>");
@@ -2050,7 +2080,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
             sb.append(module.getName());
             sb.append("</b>");
             sb.append(NEW_LINE);
-            sb.append("<br />(Source path: <i>");
+            sb.append("<br>(Source path: <i>");
             sb.append(module.getModuleSourcePath());
             sb.append("</i>):");
             sb.append(NEW_LINE);
@@ -2072,11 +2102,16 @@ public class BindingGeneratorImpl implements BindingGenerator {
                 sb.append(NEW_LINE);
                 sb.append("@see ");
                 sb.append(linkToBuilderClass);
+                sb.append(NEW_LINE);
                 if (schemaNode instanceof ListSchemaNode) {
-                    sb.append("@see ");
-                    sb.append(linkToKeyClass);
+                    final List<QName> keyDef = ((ListSchemaNode)schemaNode).getKeyDefinition();
+                    if (keyDef != null && !keyDef.isEmpty()) {
+                        sb.append("@see ");
+                        sb.append(className);
+                        sb.append("Key");
+                    }
+                   sb.append(NEW_LINE);
                 }
-                sb.append(NEW_LINE);
             }
         }
 
@@ -2110,7 +2145,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
             sb.append(module.getName());
             sb.append("</b>");
             sb.append(NEW_LINE);
-            sb.append("<br />Source path: <i>");
+            sb.append("<br>Source path: <i>");
             sb.append(module.getModuleSourcePath());
             sb.append("</i>):");
             sb.append(NEW_LINE);
@@ -2124,8 +2159,8 @@ public class BindingGeneratorImpl implements BindingGenerator {
     }
 
     private GeneratedTypeBuilder findChildNodeByPath(final SchemaPath path) {
-        for (ModuleContext ctx : genCtx.values()) {
-            GeneratedTypeBuilder result = ctx.getChildNode(path);
+        for (final ModuleContext ctx : genCtx.values()) {
+            final GeneratedTypeBuilder result = ctx.getChildNode(path);
             if (result != null) {
                 return result;
             }
@@ -2134,8 +2169,8 @@ public class BindingGeneratorImpl implements BindingGenerator {
     }
 
     private GeneratedTypeBuilder findGroupingByPath(final SchemaPath path) {
-        for (ModuleContext ctx : genCtx.values()) {
-            GeneratedTypeBuilder result = ctx.getGrouping(path);
+        for (final ModuleContext ctx : genCtx.values()) {
+            final GeneratedTypeBuilder result = ctx.getGrouping(path);
             if (result != null) {
                 return result;
             }
@@ -2144,8 +2179,8 @@ public class BindingGeneratorImpl implements BindingGenerator {
     }
 
     private GeneratedTypeBuilder findCaseByPath(final SchemaPath path) {
-        for (ModuleContext ctx : genCtx.values()) {
-            GeneratedTypeBuilder result = ctx.getCase(path);
+        for (final ModuleContext ctx : genCtx.values()) {
+            final GeneratedTypeBuilder result = ctx.getCase(path);
             if (result != null) {
                 return result;
             }