Binding generator v2 - fix IdentifiableItem and Item
[mdsal.git] / binding2 / mdsal-binding2-generator-impl / src / main / java / org / opendaylight / mdsal / binding / javav2 / generator / impl / GenHelperUtil.java
index 11ac9465a138eead5950c6a9729e82432a176608..3b46518e7c81b5620023d3a89397625b19307b99 100644 (file)
@@ -23,6 +23,8 @@ import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenU
 import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingGeneratorUtil.computeDefaultSUID;
 import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingGeneratorUtil.encodeAngleBrackets;
 import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingGeneratorUtil.packageNameForGeneratedType;
+import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingTypes.IDENTIFIABLE;
+import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingTypes.IDENTIFIER;
 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;
@@ -37,6 +39,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+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;
@@ -59,7 +62,6 @@ 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.GeneratedTypeBuilder;
-import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.MethodSignatureBuilder;
 import org.opendaylight.mdsal.binding.javav2.spec.base.BaseIdentity;
 import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode;
 import org.opendaylight.mdsal.binding.javav2.spec.runtime.BindingNamespaceType;
@@ -68,8 +70,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.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;
@@ -88,7 +90,6 @@ import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 import org.opendaylight.yangtools.yang.model.api.Status;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.UsesNode;
-import org.opendaylight.yangtools.yang.model.api.meta.ModelStatement;
 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;
@@ -125,9 +126,9 @@ final class GenHelperUtil {
                 genCtx.get(module));
         addImplementedInterfaceFromUses(module, moduleDataTypeBuilder, genCtx);
         moduleDataTypeBuilder.addImplementsType(BindingTypes.TREE_ROOT);
-        moduleDataTypeBuilder.addComment(module.getDescription());
+        moduleDataTypeBuilder.addComment(module.getDescription().orElse(null));
         moduleDataTypeBuilder.setDescription(createDescription(module, verboseClassComments));
-        moduleDataTypeBuilder.setReference(module.getReference());
+        moduleDataTypeBuilder.setReference(module.getReference().orElse(null));
         return moduleDataTypeBuilder;
     }
 
@@ -147,7 +148,7 @@ final class GenHelperUtil {
      *             if <code>module</code> is null
      */
     static GeneratedTypeBuilder moduleTypeBuilder(final Module module, final String postfix, final boolean
-            verboseClassComments, ModuleContext context) {
+            verboseClassComments, final ModuleContext context) {
         Preconditions.checkArgument(module != null, "Module reference cannot be NULL.");
         final String packageName = BindingMapping.getRootPackageName(module);
         // underscore used as separator for distinction of module name parts
@@ -155,7 +156,7 @@ final class GenHelperUtil {
 
         final GeneratedTypeBuilderImpl moduleBuilder = new GeneratedTypeBuilderImpl(packageName, moduleName, context);
         moduleBuilder.setDescription(createDescription(module, verboseClassComments));
-        moduleBuilder.setReference(module.getReference());
+        moduleBuilder.setReference(module.getReference().orElse(null));
         moduleBuilder.setModuleName(moduleName);
         return moduleBuilder;
     }
@@ -257,16 +258,11 @@ final class GenHelperUtil {
             final DataSchemaNode schemaNode) {
         if (!schemaNode.isAugmenting()) {
             return true;
-        } else if (schemaNode.isAugmenting()) {
-            QName qname = schemaNode.getPath().getLastComponent();
-            final Module originalModule = schemaContext.findModuleByNamespaceAndRevision(qname.getNamespace(),
-                    qname.getRevision());
-            if (module.equals(originalModule)) {
-                return true;
-            }
         }
 
-        return false;
+        final QName qname = schemaNode.getPath().getLastComponent();
+        final Module originalModule = schemaContext.findModule(qname.getModule()).get();
+        return module.equals(originalModule);
     }
 
     static GeneratedTypeBuilder addDefaultInterfaceDefinition(final String basePackageName, final SchemaNode
@@ -280,14 +276,13 @@ final class GenHelperUtil {
     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).getNamespace(), ((Module) node).getRevision(),
-                    superChildNode.getQName().getLocalName());
+            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) {
-            childNodeQName = QName.create(module.getNamespace(), module.getRevision(), superChildNode.getQName().getLocalName());
+        } else if (node instanceof AugmentationSchemaNode) {
+            childNodeQName = QName.create(module.getQNameModule(), superChildNode.getQName().getLocalName());
         } else {
-            throw new IllegalArgumentException("Not support node type:" + node.toString());
+            throw new IllegalArgumentException("Not support node type:" + node);
         }
 
         return childNodeQName;
@@ -295,19 +290,19 @@ final class GenHelperUtil {
 
     private static void addUsesImplements(final SchemaNode superNode, final Module superModule,
             final Object node, final Module module, final SchemaContext schemaContext,
-            Map<Module, ModuleContext> genCtx, final BindingNamespaceType namespaceType) {
+            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);
-                    Preconditions.checkNotNull(childNode, node.toString() + "->" + childQName.toString());
+                    Preconditions.checkNotNull(childNode, "%s->%s", node, childQName);
 
                     final GeneratedTypeBuilder type = genCtx.get(module).getChildNode(childNode.getPath());
                     final GeneratedTypeBuilder superType = genCtx.get(superModule).getChildNode(superChildNode.getPath());
 
-                    Preconditions.checkNotNull(type, module.toString() + "->" + childNode.getPath().toString());
-                    Preconditions.checkNotNull(superType, superModule.toString() + "->" + superChildNode.getPath().toString());
+                    Preconditions.checkNotNull(type, "%s->%s", module, childNode.getPath());
+                    Preconditions.checkNotNull(superType, "%s->%s", superModule, superChildNode.getPath());
                     type.addImplementsType(superType);
                     if (superChildNode instanceof ListSchemaNode
                             && !((ListSchemaNode) superChildNode).getKeyDefinition().isEmpty()) {
@@ -323,20 +318,20 @@ final class GenHelperUtil {
                 }
             }
         } 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);
-                ChoiceCaseNode caseNode = ((ChoiceSchemaNode) node).getCaseNodeByName(childQName);
-                Preconditions.checkNotNull(caseNode, node.toString() + "->" + childQName.toString());
+                CaseSchemaNode caseNode = ((ChoiceSchemaNode) node).getCaseNodeByName(childQName);
+                Preconditions.checkNotNull(caseNode, "%s->%s", node, childQName);
 
                 final GeneratedTypeBuilder type = genCtx.get(module).getCase(caseNode.getPath());
                 final GeneratedTypeBuilder superType = genCtx.get(superModule).getCase(superCaseNode.getPath());
-                Preconditions.checkNotNull(type, module.toString() + "->" + caseNode.getPath().toString());
-                Preconditions.checkNotNull(superType, superModule.toString() + "->" + superCaseNode.getPath().toString());
+                Preconditions.checkNotNull(type, "%s->%s", module, caseNode.getPath());
+                Preconditions.checkNotNull(superType, "%s->%s", superModule, superCaseNode.getPath());
                 type.addImplementsType(superType);
                 addUsesImplements(superCaseNode, superModule, caseNode, module, schemaContext, genCtx, namespaceType);
             }
         } else {
-            throw new IllegalArgumentException("Not support super node :" + superNode.toString());
+            throw new IllegalArgumentException("Not support super node :" + superNode);
         }
     }
 
@@ -344,25 +339,34 @@ final class GenHelperUtil {
             final Object parentNode, final UsesNode usesNode) {
         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);
         } else {
             //FIXME: Schema path is not unique for Yang 1.1, findDataSchemaNode always does search from data node first.
-            groupingNode = SchemaContextUtil.findDataSchemaNode(schemaContext, usesNode.getGroupingPath());
+            final Iterable<QName> prefixedPath = usesNode.getGroupingPath().getPathFromRoot();
+            final QName current = prefixedPath.iterator().next();
+            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());
+            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());
+            }
         }
-        Preconditions.checkNotNull(groupingNode, module.toString() + "->"
-                + usesNode.getGroupingPath().toString());
-        Preconditions.checkState(groupingNode instanceof GroupingDefinition,
-                module.toString() + "->" + usesNode.getGroupingPath().toString());
+
+        Preconditions.checkNotNull(groupingNode, "%s->%s", module, usesNode.getGroupingPath());
+        Preconditions.checkState(groupingNode instanceof GroupingDefinition, "%s->%s", module,
+            usesNode.getGroupingPath());
         return (GroupingDefinition) groupingNode;
     }
 
     static Map<Module, ModuleContext> processUsesImplements(final Object node, final Module module,
-            final SchemaContext schemaContext, 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);
@@ -393,21 +397,23 @@ final class GenHelperUtil {
         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,
-            final SchemaContext schemaContext, final boolean verboseClassComments, final TypeProvider typeProvider,
+    static Map<Module, ModuleContext> addRawAugmentGenTypeDefinition(final Module module,
+            final String augmentPackageName, final Type targetTypeRef, 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 AugmentationSchema augSchema = schemaPathAugmentListEntry.get(0);
+        final AugmentationSchemaNode augSchema = schemaPathAugmentListEntry.get(0);
 
         Map<String, GeneratedTypeBuilder> augmentBuilders = genTypeBuilders.computeIfAbsent(
                 augmentPackageName, k -> new HashMap<>());
 
         //this requires valid semantics in YANG model
         String augIdentifier = null;
-        for (AugmentationSchema aug : schemaPathAugmentListEntry) {
+        for (AugmentationSchemaNode aug : schemaPathAugmentListEntry) {
             augIdentifier = getAugmentIdentifier(aug.getUnknownSchemaNodes());
             break;
         }
@@ -428,11 +434,12 @@ final class GenHelperUtil {
         annotateDeprecatedIfNecessary(augSchema.getStatus(), augTypeBuilder);
 
         //produces getters for augTypeBuilder eventually
-        for (AugmentationSchema aug : schemaPathAugmentListEntry) {
+        for (AugmentationSchemaNode aug : schemaPathAugmentListEntry) {
             //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, augTypeBuilder,
+                aug.getChildNodes(), genCtx, schemaContext, verboseClassComments, typeProvider, genTypeBuilders,
+                namespaceType);
         }
 
         augmentBuilders.put(augTypeBuilder.getName(), augTypeBuilder);
@@ -524,14 +531,12 @@ final class GenHelperUtil {
             if (parent == null) {
                 it.addImplementsType(BindingTypes.TREE_NODE);
             } else {
-                if (parent instanceof ListSchemaNode) {
+                if (!(schemaNode instanceof ListSchemaNode) ||
+                        ((ListSchemaNode) schemaNode).getKeyDefinition().isEmpty()) {
                     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));
+                            (BindingTypes.ITEM, it)));
                 }
+                it.addImplementsType(parameterizedTypeFor(BindingTypes.INSTANTIABLE, it));
             }
 
             if (!(schemaNode instanceof GroupingDefinition)) {
@@ -550,10 +555,10 @@ final class GenHelperUtil {
         return it;
     }
 
-    static GeneratedTypeBuilder resolveNotification(final GeneratedTypeBuilder listenerInterface, String
+    static GeneratedTypeBuilder resolveNotification(final GeneratedTypeBuilder listenerInterface, final String
             parentName, final String basePackageName, final NotificationDefinition notification, final Module module,
-            final SchemaContext schemaContext, final boolean verboseClassComments, Map<String, Map<String, GeneratedTypeBuilder>>
-            genTypeBuilders, TypeProvider typeProvider, Map<Module, ModuleContext> genCtx) {
+            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);
@@ -575,7 +580,7 @@ final class GenHelperUtil {
 
         listenerInterface.addMethod(JavaIdentifierNormalizer.normalizeSpecificIdentifier(sb.toString(), JavaIdentifier.METHOD))
                 .setAccessModifier(AccessModifier.PUBLIC).addParameter(notificationInterface, "notification")
-                .setComment(encodeAngleBrackets(notification.getDescription())).setReturnType(Types.VOID);
+                .setComment(encodeAngleBrackets(notification.getDescription().orElse(null))).setReturnType(Types.VOID);
         return listenerInterface;
     }
 
@@ -607,7 +612,7 @@ final class GenHelperUtil {
     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, ModuleContext context) {
+            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.");
@@ -628,10 +633,10 @@ 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());
-        newType.addComment(schemaNode.getDescription());
+        newType.addComment(schemaNode.getDescription().orElse(null));
         newType.setDescription(createDescription(schemaNode, newType.getFullyQualifiedName(), schemaContext,
                 verboseClassComments, namespaceType));
-        newType.setReference(schemaNode.getReference());
+        newType.setReference(schemaNode.getReference().orElse(null));
         newType.setSchemaPath((List<QName>) schemaNode.getPath().getPathFromRoot());
         newType.setModuleName(module.getName());
         newType.setBasePackageName(BindingMapping.getRootPackageName(module));
@@ -671,7 +676,7 @@ final class GenHelperUtil {
                 listToGenType(module, basePackageName, typeBuilder, childOf, (ListSchemaNode) node, schemaContext,
                         verboseClassComments, genCtx, genTypeBuilders, typeProvider, namespaceType);
             } else if (node instanceof ChoiceSchemaNode) {
-                choiceToGenType(module, schemaContext, verboseClassComments, basePackageName, childOf,
+                choiceToGenType(module, schemaContext, verboseClassComments, basePackageName, typeBuilder,
                         (ChoiceSchemaNode) node, genTypeBuilders, genCtx, typeProvider, namespaceType);
             } else if (node instanceof AnyXmlSchemaNode || node instanceof AnyDataSchemaNode) {
                 resolveAnyNodeAsMethod(schemaContext, typeBuilder, genCtx, node, module, typeProvider);
@@ -712,7 +717,7 @@ final class GenHelperUtil {
         final GeneratedTypeBuilder choiceTypeBuilder = addRawInterfaceDefinition(basePackageName, choiceNode,
                 schemaContext, "", "", verboseClasssComments, genTypeBuilders, namespaceType, genCtx.get(module));
         constructGetter(parent, choiceNode.getQName().getLocalName(),
-                choiceNode.getDescription(), choiceTypeBuilder, choiceNode.getStatus());
+                choiceNode.getDescription().orElse(null), choiceTypeBuilder, choiceNode.getStatus());
         if (namespaceType.equals(BindingNamespaceType.Data)) {
             choiceTypeBuilder.addImplementsType(parameterizedTypeFor(BindingTypes.INSTANTIABLE, choiceTypeBuilder));
         }
@@ -732,7 +737,7 @@ final class GenHelperUtil {
                 schemaContext, verboseClassComments, genCtx, genTypeBuilders, typeProvider, namespaceType);
         if (genType != null) {
             StringBuilder getterName = new StringBuilder(node.getQName().getLocalName());
-            final MethodSignatureBuilder getter = 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);
@@ -755,7 +760,7 @@ final class GenHelperUtil {
                 getterReturnType = Types.listTypeFor(wildcardTypeFor(genType.getPackageName(), genType.getName(),
                                 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(),
@@ -773,21 +778,31 @@ final class GenHelperUtil {
                     typeBuildersToGenTypes(module, genType, genTypeBuilder.toInstance(), genCtx, namespaceType);
                     genCtx.get(module).addKeyType(node.getPath(), genTypeBuilder);
                 }
+                processUsesImplements(node, module, schemaContext, genCtx, namespaceType);
             } else {
                 final GeneratedTOBuilder genTOBuilder = resolveListKeyTOBuilder(packageName, node, genCtx.get(module));
+                if (genTOBuilder != null) {
+                    final Type identifiableMarker = Types.parameterizedTypeFor(IDENTIFIABLE, genTOBuilder);
+                    genTOBuilder.addImplementsType(IDENTIFIER);
+                    genType.addImplementsType(identifiableMarker);
+                    genType.addImplementsType(parameterizedTypeFor(BindingTypes.TREE_CHILD_NODE, parent, parameterizedTypeFor
+                        (BindingTypes.IDENTIFIABLE_ITEM, genType, genTOBuilder)));
+
+                }
+
                 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);
                     }
                 }
+                processUsesImplements(node, module, schemaContext, genCtx, namespaceType);
 
                 // serialVersionUID
                 if (genTOBuilder != null) {
                     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);
                 }
@@ -805,7 +820,7 @@ final class GenHelperUtil {
                 returnKeyType = wildcardTypeFor(keyType.getPackageName(), keyType.getName(),
                         true, true, null);
             }
-            constructGetter(typeBuilder, "key", "Returns Primary Key of Yang List Type", returnKeyType, Status.CURRENT);
+            constructGetter(typeBuilder, "identifier", "Returns Primary Key of Yang List Type", returnKeyType, Status.CURRENT);
 
         }
     }
@@ -845,7 +860,25 @@ final class GenHelperUtil {
         Type returnType = null;
 
         final TypeDefinition<?> typeDef = leaf.getType();
-        if (isInnerType(leaf, typeDef)) {
+
+        if (leaf.isAddedByUses()) {
+            Preconditions.checkState(leaf instanceof DerivableSchemaNode);
+            if (isInnerType(leaf, typeDef)) {
+                final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
+                returnType = typeProvider.javaTypeForSchemaDefinitionType(getBaseOrDeclaredType(typeDef), leaf,
+                        restrictions, genCtx.get(module));
+            } else {
+                if (typeDef.getBaseType() == null && (typeDef instanceof EnumTypeDefinition
+                        || typeDef instanceof UnionTypeDefinition || typeDef instanceof BitsTypeDefinition)) {
+                    LeafSchemaNode originalLeaf = (LeafSchemaNode) ((DerivableSchemaNode) leaf).getOriginal().orElse(null);
+                    Preconditions.checkNotNull(originalLeaf);
+                    returnType = genCtx.get(findParentModule(schemaContext, originalLeaf)).getInnerType(typeDef.getPath());
+                } else {
+                    final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
+                    returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf, restrictions, genCtx.get(module));
+                }
+            }
+        } else if (isInnerType(leaf, typeDef)) {
             if (typeDef instanceof EnumTypeDefinition) {
                 returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf, genCtx.get(module));
                 final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) typeDef;
@@ -857,14 +890,14 @@ final class GenHelperUtil {
                 ((TypeProviderImpl) typeProvider).putReferencedType(leaf.getPath(), returnType);
             } else if (typeDef instanceof UnionTypeDefinition) {
                 final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leaf, parentModule,
-                        typeProvider, schemaContext, genCtx.get(module));
+                        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);
                 }
             } else if (typeDef instanceof BitsTypeDefinition) {
                 final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leaf, parentModule,
-                        typeProvider, schemaContext, genCtx.get(module));
+                        typeProvider, schemaContext, genCtx.get(module), genCtx);
                 if (genTOBuilder != null) {
                     returnType = genTOBuilder.toInstance();
                 }
@@ -890,11 +923,6 @@ final class GenHelperUtil {
             ((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)
@@ -903,7 +931,7 @@ final class GenHelperUtil {
         } else {
             leafGetterName = leafName;
         }
-        constructGetter(typeBuilder, leafGetterName, leafDesc, returnType, leaf.getStatus());
+        constructGetter(typeBuilder, leafGetterName, leaf.getDescription().orElse(""), returnType, leaf.getStatus());
         return returnType;
     }
 
@@ -946,18 +974,18 @@ final class GenHelperUtil {
                 final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) typeDef;
                 final EnumBuilder enumBuilder = resolveInnerEnumFromTypeDefinition(enumTypeDef, nodeName,
                         genCtx, typeBuilder, module);
-                returnType = new ReferencedTypeImpl(enumBuilder.getPackageName(), enumBuilder.getName(),
-                        genCtx.get(module));
+                returnType = new ReferencedTypeImpl(enumBuilder.getPackageName(), enumBuilder.getName(), true,
+                        null);
                 ((TypeProviderImpl) typeProvider).putReferencedType(node.getPath(), returnType);
             } else if (typeDef instanceof UnionTypeDefinition) {
                 final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, node, parentModule,
-                        typeProvider, schemaContext, genCtx.get(module));
+                        typeProvider, schemaContext, genCtx.get(module), genCtx);
                 if (genTOBuilder != null) {
                     returnType = createReturnTypeForUnion(genTOBuilder, typeDef, typeBuilder, parentModule, typeProvider);
                 }
             } else if (typeDef instanceof BitsTypeDefinition) {
                 final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, node, parentModule,
-                        typeProvider, schemaContext, genCtx.get(module));
+                        typeProvider, schemaContext, genCtx.get(module), genCtx);
                 returnType = genTOBuilder.toInstance();
             } else {
                 final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
@@ -969,7 +997,7 @@ final class GenHelperUtil {
         }
 
         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;
     }
 
@@ -1013,12 +1041,7 @@ final class GenHelperUtil {
         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,
                     module, genCtx, schemaContext, verboseClassComments, genTypeBuilders, typeProvider, namespaceType);
@@ -1034,14 +1057,14 @@ final class GenHelperUtil {
                     if (!Iterables.isEmpty(choiceNodeParentPath.getPathFromRoot())) {
                         SchemaNode parent = findDataSchemaNode(schemaContext, choiceNodeParentPath);
 
-                        if (parent instanceof AugmentationSchema) {
-                            final AugmentationSchema augSchema = (AugmentationSchema) parent;
+                        if (parent instanceof AugmentationSchemaNode) {
+                            final AugmentationSchemaNode augSchema = (AugmentationSchemaNode) 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();
+                                    targetSchemaNode = ((DerivableSchemaNode) targetSchemaNode).getOriginal().orElse(null);
                                 }
                                 if (targetSchemaNode == null) {
                                     throw new IllegalStateException(
@@ -1061,10 +1084,12 @@ final class GenHelperUtil {
                         resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, childOfType, caseChildNodes,
                                 genCtx, schemaContext, verboseClassComments, genTypeBuilders, typeProvider, namespaceType);
                     } else {
-                        resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, moduleToDataType(module,
-                                genCtx, verboseClassComments), caseChildNodes, genCtx, schemaContext,
-                                verboseClassComments, genTypeBuilders, typeProvider, namespaceType);
+                        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);
                 }
             }
         }
@@ -1079,14 +1104,8 @@ final class GenHelperUtil {
             return null;
         }
 
-        String anyDesc = node.getDescription();
-        if (anyDesc == null) {
-            anyDesc = "";
-        }
-
         Type returnType = Types.DOCUMENT;
-
-        constructGetter(typeBuilder, anyName, anyDesc, returnType, node.getStatus());
+        constructGetter(typeBuilder, anyName, node.getDescription().orElse(""), returnType, node.getStatus());
         return returnType;
     }
 
@@ -1212,16 +1231,14 @@ final class GenHelperUtil {
                 // 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 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));
@@ -1233,23 +1250,23 @@ final class GenHelperUtil {
 
     private static TypeDefinition<?> getBaseOrDeclaredType(final TypeDefinition<?> typeDef) {
         final TypeDefinition<?> baseType = typeDef.getBaseType();
-        return (baseType != null && baseType.getBaseType() != null) ? baseType : typeDef;
+        return baseType != null && baseType.getBaseType() != null ? baseType : typeDef;
     }
 
     @SuppressWarnings({ "rawtypes", "unchecked" })
     private static GeneratedTypeBuilder processDataSchemaNode(final Module module, final String basePackageName,
         final GeneratedTypeBuilder childOf, final DataSchemaNode node, final SchemaContext schemaContext,
-        final boolean verboseClassComments, Map<Module, ModuleContext> genCtx, final Map<String, Map<String,
+        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);
-        genType.addComment(node.getDescription());
+        genType.addComment(node.getDescription().orElse(null));
         annotateDeprecatedIfNecessary(node.getStatus(), genType);
         genType.setDescription(createDescription(node, genType.getFullyQualifiedName(), schemaContext,
                 verboseClassComments, namespaceType));
         genType.setModuleName(module.getName());
-        genType.setReference(node.getReference());
+        genType.setReference(node.getReference().orElse(null));
         genType.setSchemaPath((List) node.getPath().getPathFromRoot());
         genType.setParentTypeForBuilder(childOf);
         if (node instanceof DataNodeContainer) {
@@ -1283,7 +1300,7 @@ final class GenHelperUtil {
      */
     static Map<Module, ModuleContext> groupingsToGenTypes(final Module module, final Collection<GroupingDefinition>
             groupings, Map<Module, ModuleContext> genCtx, final SchemaContext schemaContext, final boolean
-            verboseClassComments, 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);
@@ -1321,7 +1338,7 @@ final class GenHelperUtil {
      */
     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, Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders, final TypeProvider typeProvider) {
+            verboseClassComments, final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders, final TypeProvider typeProvider) {
         final GeneratedTypeBuilder genType = addDefaultInterfaceDefinition(basePackageName, grouping, module, genCtx,
                 schemaContext, verboseClassComments, genTypeBuilders, typeProvider, BindingNamespaceType.Grouping);
         annotateDeprecatedIfNecessary(grouping.getStatus(), genType);
@@ -1354,8 +1371,8 @@ final class GenHelperUtil {
      * @return returns generated context
      */
     static Map<Module, ModuleContext> identityToGenType(final Module module, final String basePackageName,
-            final IdentitySchemaNode identity, final SchemaContext schemaContext, Map<Module, ModuleContext> genCtx,
-            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;
@@ -1394,10 +1411,10 @@ final class GenHelperUtil {
             }
 
             newType.setAbstract(true);
-            newType.addComment(identity.getDescription());
+            newType.addComment(identity.getDescription().orElse(null));
             newType.setDescription(createDescription(identity, newType.getFullyQualifiedName(), schemaContext,
                     verboseClassComments, BindingNamespaceType.Identity));
-            newType.setReference(identity.getReference());
+            newType.setReference(identity.getReference().orElse(null));
             newType.setModuleName(module.getName());
             newType.setSchemaPath((List) identity.getPath().getPathFromRoot());