Revert "Rework inlined union generation"
[mdsal.git] / binding2 / mdsal-binding2-generator-impl / src / main / java / org / opendaylight / mdsal / binding / javav2 / generator / impl / GenHelperUtil.java
old mode 100644 (file)
new mode 100755 (executable)
index 28aba87..ee592c5
@@ -27,18 +27,18 @@ import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingTypes.
 import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingTypes.NOTIFICATION;
 import static org.opendaylight.mdsal.binding.javav2.generator.util.Types.parameterizedTypeFor;
 import static org.opendaylight.mdsal.binding.javav2.generator.util.Types.wildcardTypeFor;
-import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNode;
+import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.resolveRegExpressions;
 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findParentModule;
 
 import com.google.common.annotations.Beta;
 import com.google.common.base.Preconditions;
-import com.google.common.collect.Iterables;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
+import javax.annotation.Nullable;
 import org.opendaylight.mdsal.binding.javav2.generator.context.ModuleContext;
 import org.opendaylight.mdsal.binding.javav2.generator.spi.TypeProvider;
 import org.opendaylight.mdsal.binding.javav2.generator.util.BindingGeneratorUtil;
@@ -49,8 +49,8 @@ import org.opendaylight.mdsal.binding.javav2.generator.util.ReferencedTypeImpl;
 import org.opendaylight.mdsal.binding.javav2.generator.util.TypeComments;
 import org.opendaylight.mdsal.binding.javav2.generator.util.Types;
 import org.opendaylight.mdsal.binding.javav2.generator.util.generated.type.builder.GeneratedPropertyBuilderImpl;
-import org.opendaylight.mdsal.binding.javav2.generator.util.generated.type.builder.GeneratedTOBuilderImpl;
 import org.opendaylight.mdsal.binding.javav2.generator.util.generated.type.builder.GeneratedTypeBuilderImpl;
+import org.opendaylight.mdsal.binding.javav2.generator.yang.types.BaseYangTypes;
 import org.opendaylight.mdsal.binding.javav2.generator.yang.types.GroupingDefinitionDependencySort;
 import org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeProviderImpl;
 import org.opendaylight.mdsal.binding.javav2.model.api.AccessModifier;
@@ -93,6 +93,7 @@ import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.UsesNode;
 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
 import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
 import org.opendaylight.yangtools.yang.model.util.SchemaNodeUtils;
@@ -129,7 +130,7 @@ final class GenHelperUtil {
         moduleDataTypeBuilder.addImplementsType(BindingTypes.TREE_ROOT);
 
         if (verboseClassComments) {
-            moduleDataTypeBuilder.setYangSourceDefinition(YangSourceDefinition.of(module));
+            YangSourceDefinition.of(module).ifPresent(moduleDataTypeBuilder::setYangSourceDefinition);
             TypeComments.description(module).ifPresent(moduleDataTypeBuilder::addComment);
             module.getDescription().ifPresent(moduleDataTypeBuilder::setDescription);
             module.getReference().ifPresent(moduleDataTypeBuilder::setReference);
@@ -162,7 +163,7 @@ final class GenHelperUtil {
 
         final GeneratedTypeBuilderImpl moduleBuilder = new GeneratedTypeBuilderImpl(packageName, moduleName, context);
         if (verboseClassComments) {
-            moduleBuilder.setYangSourceDefinition(YangSourceDefinition.of(module));
+            YangSourceDefinition.of(module).ifPresent(moduleBuilder::setYangSourceDefinition);
             TypeComments.description(module).ifPresent(moduleBuilder::addComment);
             module.getDescription().ifPresent(moduleBuilder::setDescription);
             module.getReference().ifPresent(moduleBuilder::setReference);
@@ -211,9 +212,9 @@ final class GenHelperUtil {
         return null;
      }
 
-    static GeneratedTOBuilder findIdentityByQname(final QName qname, final Map<Module, ModuleContext> genCtx) {
+    static GeneratedTypeBuilder findIdentityByQname(final QName qname, final Map<Module, ModuleContext> genCtx) {
         for (final ModuleContext ctx : genCtx.values()) {
-            final GeneratedTOBuilder result = ctx.getIdentities().get(qname);
+            final GeneratedTypeBuilder result = ctx.getIdentities().get(qname);
             if (result != null) {
                 return result;
             }
@@ -275,14 +276,6 @@ final class GenHelperUtil {
         return module.equals(originalModule);
     }
 
-    static GeneratedTypeBuilder addDefaultInterfaceDefinition(final String basePackageName, final SchemaNode
-            schemaNode, final Module module, final Map<Module, ModuleContext> genCtx, final SchemaContext schemaContext,
-            final boolean verboseClassComments, final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders,
-            final TypeProvider typeProvider, final BindingNamespaceType namespaceType) {
-        return addDefaultInterfaceDefinition(basePackageName, schemaNode, null, module, genCtx, schemaContext,
-                verboseClassComments, genTypeBuilders, typeProvider , namespaceType);
-    }
-
     private static QName createQNameFromSuperNode(final Module module, final Object node, final SchemaNode superChildNode) {
         QName childNodeQName = null;
         if (node instanceof Module) {
@@ -520,40 +513,36 @@ final class GenHelperUtil {
      *            string contains the module package name
      * @param schemaNode
      *            schema node for which is created generated type builder
-     * @param parent
-     *            parent type (can be null)
+     * @param childOf
+     *            parent generated type of data tree node, which should be
+     *            set null if current schema node is not a data tree node.
      * @param schemaContext schema context
      * @return generated type builder <code>schemaNode</code>
      */
-    private static GeneratedTypeBuilder addDefaultInterfaceDefinition(final String basePackageName, final SchemaNode
-            schemaNode, final Type parent, final Module module, final Map<Module, ModuleContext> genCtx,
+    public static GeneratedTypeBuilder addDefaultInterfaceDefinition(final String basePackageName, final SchemaNode
+            schemaNode, @Nullable final Type childOf, final Module module, final Map<Module, ModuleContext> genCtx,
             final SchemaContext schemaContext, final boolean verboseClassComments, final Map<String, Map<String,
             GeneratedTypeBuilder>> genTypeBuilders, final TypeProvider typeProvider, final BindingNamespaceType namespaceType) {
 
-        String suffix = "";
-        if (schemaNode instanceof GroupingDefinition) {
-            suffix = "grouping";
-        } else if (namespaceType.equals(BindingNamespaceType.Grouping)) {
-            suffix = "data";
-        }
-
-        GeneratedTypeBuilder it = addRawInterfaceDefinition(basePackageName, schemaNode, schemaContext, "", suffix,
+        GeneratedTypeBuilder it = addRawInterfaceDefinition(basePackageName, schemaNode, schemaContext, "", "",
                 verboseClassComments, genTypeBuilders, namespaceType, genCtx.get(module));
+
         if (namespaceType.equals(BindingNamespaceType.Data)) {
-            if (parent == null) {
+            if (childOf == null) {
                 it.addImplementsType(BindingTypes.TREE_NODE);
             } else {
                 if (!(schemaNode instanceof ListSchemaNode) ||
                         ((ListSchemaNode) schemaNode).getKeyDefinition().isEmpty()) {
-                    it.addImplementsType(parameterizedTypeFor(BindingTypes.TREE_CHILD_NODE, parent, parameterizedTypeFor
-                            (BindingTypes.ITEM, it)));
+                    it.addImplementsType(parameterizedTypeFor(BindingTypes.TREE_CHILD_NODE, childOf,
+                        parameterizedTypeFor(BindingTypes.ITEM, it)));
                 }
-                it.addImplementsType(parameterizedTypeFor(BindingTypes.INSTANTIABLE, it));
             }
 
-            if (!(schemaNode instanceof GroupingDefinition)) {
-                it.addImplementsType(BindingTypes.augmentable(it));
+            if (!(schemaNode instanceof CaseSchemaNode)) {
+                it.addImplementsType(parameterizedTypeFor(BindingTypes.INSTANTIABLE, it));
             }
+
+            it.addImplementsType(BindingTypes.augmentable(it));
         } else {
             it.addImplementsType(BindingTypes.TREE_NODE);
         }
@@ -576,7 +565,6 @@ final class GenHelperUtil {
                         verboseClassComments, genTypeBuilders, typeProvider, BindingNamespaceType.Data);
         annotateDeprecatedIfNecessary(notification.getStatus(), notificationInterface);
         notificationInterface.addImplementsType(NOTIFICATION);
-        notificationInterface.addImplementsType(parameterizedTypeFor(BindingTypes.INSTANTIABLE, notificationInterface));
         genCtx.get(module).addChildNodeType(notification, notificationInterface);
 
         // Notification object
@@ -647,7 +635,7 @@ final class GenHelperUtil {
         final Module module = SchemaContextUtil.findParentModule(schemaContext, schemaNode);
         qNameConstant(newType, BindingMapping.QNAME_STATIC_FIELD_NAME, schemaNode.getQName());
         if (verboseClassComments) {
-            newType.setYangSourceDefinition(YangSourceDefinition.of(module, schemaNode));
+            YangSourceDefinition.of(module, schemaNode).ifPresent(newType::setYangSourceDefinition);
             TypeComments.description(schemaNode).ifPresent(newType::addComment);
             schemaNode.getDescription().ifPresent(newType::setDescription);
             schemaNode.getReference().ifPresent(newType::setReference);
@@ -691,7 +679,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, typeBuilder,
+                choiceToGenType(module, schemaContext, verboseClassComments, basePackageName, typeBuilder, childOf,
                         (ChoiceSchemaNode) node, genTypeBuilders, genCtx, typeProvider, namespaceType);
             } else if (node instanceof AnyXmlSchemaNode || node instanceof AnyDataSchemaNode) {
                 resolveAnyNodeAsMethod(schemaContext, typeBuilder, genCtx, node, module, typeProvider);
@@ -723,16 +711,19 @@ final class GenHelperUtil {
      *             </ul>
      */
     private static void choiceToGenType(final Module module, final SchemaContext schemaContext, final boolean
-            verboseClasssComments, final String basePackageName, final GeneratedTypeBuilder parent, final
-            ChoiceSchemaNode choiceNode, final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders,
-            final Map<Module, ModuleContext> genCtx, final TypeProvider typeProvider, final BindingNamespaceType namespaceType) {
+            verboseClasssComments, final String basePackageName, final GeneratedTypeBuilder parent,
+            final GeneratedTypeBuilder childOf, final ChoiceSchemaNode choiceNode,
+            final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders,
+            final Map<Module, ModuleContext> genCtx, final TypeProvider typeProvider,
+            final BindingNamespaceType namespaceType) {
         checkArgument(basePackageName != null, "Base Package Name cannot be NULL.");
         checkArgument(choiceNode != null, "Choice Schema Node cannot be NULL.");
 
         final GeneratedTypeBuilder choiceTypeBuilder = addRawInterfaceDefinition(basePackageName, choiceNode,
-                schemaContext, "", "", verboseClasssComments, genTypeBuilders, namespaceType, genCtx.get(module));
+            schemaContext, "", "", verboseClasssComments, genTypeBuilders, namespaceType, genCtx.get(module));
         constructGetter(parent, choiceNode.getQName().getLocalName(),
                 choiceNode.getDescription().orElse(null), choiceTypeBuilder, choiceNode.getStatus());
+        choiceTypeBuilder.setParentTypeForBuilder(childOf);
         if (namespaceType.equals(BindingNamespaceType.Data)) {
             choiceTypeBuilder.addImplementsType(parameterizedTypeFor(BindingTypes.INSTANTIABLE, choiceTypeBuilder));
         }
@@ -800,7 +791,7 @@ final class GenHelperUtil {
                     final Type identifiableMarker = Types.parameterizedTypeFor(IDENTIFIABLE, genTOBuilder);
                     genTOBuilder.addImplementsType(IDENTIFIER);
                     genType.addImplementsType(identifiableMarker);
-                    genType.addImplementsType(parameterizedTypeFor(BindingTypes.TREE_CHILD_NODE, parent, parameterizedTypeFor
+                    genType.addImplementsType(parameterizedTypeFor(BindingTypes.TREE_CHILD_NODE, childOf, parameterizedTypeFor
                         (BindingTypes.IDENTIFIABLE_ITEM, genType, genTOBuilder)));
 
                 }
@@ -840,6 +831,18 @@ final class GenHelperUtil {
         }
     }
 
+    private static void addPatternConstant(final GeneratedTypeBuilder typeBuilder, final String leafName,
+            final List<PatternConstraint> patternConstraints) {
+        if (!patternConstraints.isEmpty()) {
+            final StringBuilder field = new StringBuilder();
+            field.append(BindingMapping.PATTERN_CONSTANT_NAME).append("_")
+                .append(JavaIdentifierNormalizer.normalizeSpecificIdentifier(leafName, JavaIdentifier.CLASS)
+                    .toUpperCase());
+            typeBuilder.addConstant(Types.listTypeFor(BaseYangTypes.STRING_TYPE), field.toString(),
+                resolveRegExpressions(patternConstraints));
+        }
+    }
+
     /**
      * Converts <code>leaf</code> to the getter method which is added to
      * <code>typeBuilder</code>.
@@ -925,10 +928,12 @@ final class GenHelperUtil {
                 final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
                 returnType = typeProvider.javaTypeForSchemaDefinitionType(getBaseOrDeclaredType(typeDef), leaf,
                         restrictions, genCtx.get(module));
+                addPatternConstant(typeBuilder, leafName, restrictions.getPatternConstraints());
             }
         } else {
             final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
             returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf, restrictions, genCtx.get(module));
+            addPatternConstant(typeBuilder, leafName, restrictions.getPatternConstraints());
         }
 
         if (returnType == null) {
@@ -1007,10 +1012,14 @@ final class GenHelperUtil {
             } else {
                 final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
                 returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, node, restrictions, genCtx.get(module));
+
+                addPatternConstant(typeBuilder, nodeName.getLocalName(), restrictions.getPatternConstraints());
             }
         } else {
             final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
             returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, node, restrictions, genCtx.get(module));
+
+            addPatternConstant(typeBuilder, nodeName.getLocalName(), restrictions.getPatternConstraints());
         }
 
         final ParameterizedType listType = Types.listTypeFor(returnType);
@@ -1051,9 +1060,10 @@ final class GenHelperUtil {
      *             </ul>
      */
     private static void generateTypesFromChoiceCases(final Module module, final SchemaContext schemaContext,
-            final Map<Module, ModuleContext> genCtx, final String basePackageName, final Type refChoiceType,
-            final ChoiceSchemaNode choiceNode, final boolean verboseClassComments, final TypeProvider typeProvider,
-            final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders, final BindingNamespaceType namespaceType) {
+            final Map<Module, ModuleContext> genCtx, final String basePackageName, final GeneratedType refChoiceType,
+            final ChoiceSchemaNode choiceNode, final boolean verboseClassComments,
+            final TypeProvider typeProvider, final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders,
+            final BindingNamespaceType namespaceType) {
         checkArgument(basePackageName != null, "Base Package Name cannot be NULL.");
         checkArgument(refChoiceType != null, "Referenced Choice Type cannot be NULL.");
         checkArgument(choiceNode != null, "ChoiceNode cannot be NULL.");
@@ -1061,53 +1071,20 @@ final class GenHelperUtil {
         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);
+                    null, module, genCtx, schemaContext, verboseClassComments,
+                    genTypeBuilders, typeProvider, namespaceType);
                 caseTypeBuilder.addImplementsType(refChoiceType);
-                caseTypeBuilder.setParentTypeForBuilder(refChoiceType);
+                caseTypeBuilder.setParentTypeForBuilder(refChoiceType.getParentTypeForBuilder());
                 annotateDeprecatedIfNecessary(caseNode.getStatus(), caseTypeBuilder);
                 genCtx.get(module).addCaseType(caseNode.getPath(), caseTypeBuilder);
-                genCtx.get(module).addChoiceToCaseMapping(refChoiceType, caseTypeBuilder, caseNode);
-                final Iterable<DataSchemaNode> caseChildNodes = caseNode.getChildNodes();
-                if (caseChildNodes != null) {
-                    final SchemaPath choiceNodeParentPath = choiceNode.getPath().getParent();
-
-                    if (!Iterables.isEmpty(choiceNodeParentPath.getPathFromRoot())) {
-                        SchemaNode parent = findDataSchemaNode(schemaContext, choiceNodeParentPath);
-
-                        if (parent instanceof 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().orElse(null);
-                                }
-                                if (targetSchemaNode == null) {
-                                    throw new IllegalStateException(
-                                            "Failed to find target node from grouping for augmentation " + augSchema
-                                                    + " in module " + module.getName());
-                                }
-                            }
-                            parent = targetSchemaNode;
-                        }
-
-                        Preconditions.checkState(parent != null, "Could not find Choice node parent %s",
-                                choiceNodeParentPath);
-                        GeneratedTypeBuilder childOfType = findChildNodeByPath(parent.getPath(), genCtx);
-                        if (childOfType == null) {
-                            childOfType = findGroupingByPath(parent.getPath(), genCtx);
-                        }
-                        resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, childOfType, caseChildNodes,
-                                genCtx, schemaContext, verboseClassComments, genTypeBuilders, typeProvider, namespaceType);
-                    } else {
-                        final GeneratedTypeBuilder moduleType = genCtx.get(module).getModuleNode();
-                        Preconditions.checkNotNull(moduleType, "Module type can not be null.");
-                        resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, moduleType, caseChildNodes,
-                            genCtx, schemaContext, verboseClassComments, genTypeBuilders, typeProvider, namespaceType);
-                    }
-                    processUsesImplements(caseNode, module, schemaContext, genCtx, namespaceType);
+                if (namespaceType.equals(BindingNamespaceType.Data)) {
+                    genCtx.get(module).addChoiceToCaseMapping(refChoiceType, caseTypeBuilder, caseNode);
                 }
+
+                resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder,
+                        (GeneratedTypeBuilder) refChoiceType.getParentTypeForBuilder(), caseNode.getChildNodes(),
+                    genCtx, schemaContext, verboseClassComments, genTypeBuilders, typeProvider, namespaceType);
+                processUsesImplements(caseNode, module, schemaContext, genCtx, namespaceType);
             }
         }
     }
@@ -1196,7 +1173,7 @@ final class GenHelperUtil {
                 listToGenType(module, basePackageName, typeBuilder, typeBuilder, (ListSchemaNode) schemaNode,
                         schemaContext, verboseClassComments, genCtx, genTypeBuilders, typeProvider, namespaceType);
             } else if (schemaNode instanceof ChoiceSchemaNode) {
-                choiceToGenType(module, schemaContext, verboseClassComments, basePackageName, typeBuilder,
+                choiceToGenType(module, schemaContext, verboseClassComments, basePackageName, typeBuilder, typeBuilder,
                         (ChoiceSchemaNode) schemaNode, genTypeBuilders, genCtx, typeProvider, namespaceType);
             }
         }
@@ -1231,7 +1208,7 @@ final class GenHelperUtil {
                 listToGenType(module, basePackageName, typeBuilder, typeBuilder, (ListSchemaNode) schemaNode,
                         schemaContext, verboseClassComments, genCtx, genTypeBuilders, typeProvider, namespaceType);
             } else if (schemaNode instanceof ChoiceSchemaNode) {
-                choiceToGenType(module, schemaContext, verboseClassComments, basePackageName, typeBuilder,
+                choiceToGenType(module, schemaContext, verboseClassComments, basePackageName, typeBuilder, typeBuilder,
                         (ChoiceSchemaNode) schemaNode, genTypeBuilders, genCtx, typeProvider, namespaceType);
             }
         }
@@ -1281,7 +1258,7 @@ final class GenHelperUtil {
         annotateDeprecatedIfNecessary(node.getStatus(), genType);
         genType.setModuleName(module.getName());
         if (verboseClassComments) {
-            genType.setYangSourceDefinition(YangSourceDefinition.of(module, node));
+            YangSourceDefinition.of(module, node).ifPresent(genType::setYangSourceDefinition);
             TypeComments.description(node).ifPresent(genType::addComment);
             node.getDescription().ifPresent(genType::setDescription);
             node.getReference().ifPresent(genType::setReference);
@@ -1358,7 +1335,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, final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders, final TypeProvider typeProvider) {
-        final GeneratedTypeBuilder genType = addDefaultInterfaceDefinition(basePackageName, grouping, module, genCtx,
+        final GeneratedTypeBuilder genType = addDefaultInterfaceDefinition(basePackageName, grouping, null, module, genCtx,
                 schemaContext, verboseClassComments, genTypeBuilders, typeProvider, BindingNamespaceType.Grouping);
         annotateDeprecatedIfNecessary(grouping.getStatus(), genType);
         genCtx.get(module).addGroupingType(grouping, genType);
@@ -1397,13 +1374,13 @@ final class GenHelperUtil {
         return genCtx;
     }
 
-    private static GeneratedTOBuilder resolveIdentitySchemaNode(final String basePackageName, final SchemaContext schemaContext,
+    private static GeneratedTypeBuilder resolveIdentitySchemaNode(final String basePackageName, final SchemaContext schemaContext,
             final IdentitySchemaNode identity, final Module module, final boolean verboseClassComments,
             final Map<Module, ModuleContext> genCtx) {
         Preconditions.checkNotNull(identity,"Identity can not be null!");
 
         //check first if identity has been resolved as base identity of some other one
-        GeneratedTOBuilder newType = findIdentityByQname(identity.getQName(), genCtx);
+        GeneratedTypeBuilder newType = findIdentityByQname(identity.getQName(), genCtx);
         if (newType == null) {
             final Module parentModule = SchemaContextUtil.findParentModule(schemaContext, identity);
             Preconditions.checkState(module.equals(parentModule),
@@ -1412,27 +1389,26 @@ final class GenHelperUtil {
 
             final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, identity.getPath(),
                     BindingNamespaceType.Identity);
-            newType = new GeneratedTOBuilderImpl(packageName, identity.getQName().getLocalName(), true, false,
+            newType = new GeneratedTypeBuilderImpl(packageName, identity.getQName().getLocalName(), true, false,
                     genCtx.get(module));
 
             final Set<IdentitySchemaNode> baseIdentities = identity.getBaseIdentities();
             if (baseIdentities.size() == 0) {
                 //no base - abstract
-                final GeneratedTOBuilderImpl gto = new GeneratedTOBuilderImpl(BaseIdentity.class.getPackage().getName(),
+                final GeneratedTypeBuilderImpl genType = new GeneratedTypeBuilderImpl(BaseIdentity.class.getPackage().getName(),
                         BaseIdentity.class.getSimpleName(), genCtx.get(module));
-                newType.setExtendsType(gto.toInstance());
+                newType.addImplementsType(genType.toInstance());
             } else {
-                //one base - inheritance
-                final IdentitySchemaNode baseIdentity = baseIdentities.iterator().next();
-                GeneratedTOBuilder baseType = resolveIdentitySchemaNode(basePackageName, schemaContext,
-                    baseIdentity, module, verboseClassComments, genCtx);
-                newType.setExtendsType(baseType.toInstance());
+                //multiple bases - inheritance
+                for (IdentitySchemaNode baseIdentity : baseIdentities) {
+                    GeneratedTypeBuilder baseType = resolveIdentitySchemaNode(basePackageName, schemaContext,
+                        baseIdentity, module, verboseClassComments, genCtx);
+                    newType.addImplementsType(baseType.toInstance());
+                }
             }
 
-            newType.setAbstract(true);
-
             if (verboseClassComments) {
-                newType.setYangSourceDefinition(YangSourceDefinition.of(module));
+                YangSourceDefinition.of(module).ifPresent(newType::setYangSourceDefinition);
                 TypeComments.description(module).ifPresent(newType::addComment);
                 module.getDescription().ifPresent(newType::setDescription);
                 module.getReference().ifPresent(newType::setReference);