Bug 8449 - BindingToNormalizedNodeCodec fails to deserialize union of leafrefs
[mdsal.git] / binding / mdsal-binding-generator-impl / src / main / java / org / opendaylight / yangtools / sal / binding / yang / types / TypeProviderImpl.java
index d568c947dd34a9893b7639c723f6607c3e47c21f..4c91e037f2f93576efc4745ad2cfd30dbd861817 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.yangtools.sal.binding.yang.types;
 
+import static org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil.encodeAngleBrackets;
 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNode;
 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNodeForRelativeXPath;
 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findParentModule;
@@ -64,6 +65,7 @@ import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 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.type.BinaryTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
@@ -78,20 +80,10 @@ import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
-import org.opendaylight.yangtools.yang.model.util.EnumerationType;
-import org.opendaylight.yangtools.yang.model.util.ExtendedType;
-import org.opendaylight.yangtools.yang.model.util.Int16;
-import org.opendaylight.yangtools.yang.model.util.Int32;
-import org.opendaylight.yangtools.yang.model.util.Int64;
-import org.opendaylight.yangtools.yang.model.util.Int8;
 import org.opendaylight.yangtools.yang.model.util.RevisionAwareXPathImpl;
 import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
-import org.opendaylight.yangtools.yang.model.util.StringType;
-import org.opendaylight.yangtools.yang.model.util.Uint16;
-import org.opendaylight.yangtools.yang.model.util.Uint32;
-import org.opendaylight.yangtools.yang.model.util.Uint64;
-import org.opendaylight.yangtools.yang.model.util.Uint8;
-import org.opendaylight.yangtools.yang.model.util.UnionType;
+import org.opendaylight.yangtools.yang.model.util.type.BaseTypes;
+import org.opendaylight.yangtools.yang.model.util.type.CompatUtils;
 import org.opendaylight.yangtools.yang.parser.util.YangValidationException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -100,6 +92,11 @@ public final class TypeProviderImpl implements TypeProvider {
     private static final Logger LOG = LoggerFactory.getLogger(TypeProviderImpl.class);
     private static final Pattern NUMBERS_PATTERN = Pattern.compile("[0-9]+\\z");
 
+    // Backwards compatibility: Union types used to be instantiated in YANG namespace, which is no longer
+    // the case, as unions are emitted to their correct schema path.
+    private static final SchemaPath UNION_PATH = SchemaPath.create(true,
+        org.opendaylight.yangtools.yang.model.util.BaseTypes.UNION_QNAME);
+
     /**
      * Contains the schema data red from YANG files.
      */
@@ -152,11 +149,11 @@ public final class TypeProviderImpl implements TypeProvider {
         Preconditions.checkArgument(refTypePath != null,
                 "Path reference of Enumeration Type Definition cannot be NULL!");
         Preconditions.checkArgument(refType != null, "Reference to Enumeration Type cannot be NULL!");
-        referencedTypes.put(refTypePath, refType);
+        this.referencedTypes.put(refTypePath, refType);
     }
 
     public Map<Module, Set<Type>> getAdditionalTypes() {
-        return additionalTypes;
+        return this.additionalTypes;
     }
 
     /**
@@ -193,41 +190,48 @@ public final class TypeProviderImpl implements TypeProvider {
      *             </ul>
      */
     @Override
-    public Type javaTypeForSchemaDefinitionType(final TypeDefinition<?> typeDefinition, final SchemaNode parentNode,
-            final Restrictions r) {
+    public Type javaTypeForSchemaDefinitionType(final TypeDefinition<?> typeDefinition, final SchemaNode parentNode, final Restrictions r) {
         Preconditions.checkArgument(typeDefinition != null, "Type Definition cannot be NULL!");
         Preconditions.checkArgument(typeDefinition.getQName() != null,
                 "Type Definition cannot have non specified QName (QName cannot be NULL!)");
-        String typedefName = typeDefinition.getQName().getLocalName();
+        final String typedefName = typeDefinition.getQName().getLocalName();
         Preconditions.checkArgument(typedefName != null, "Type Definitions Local Name cannot be NULL!");
 
-        // Deal with leafrefs/identityrefs first
-        Type returnType = javaTypeForLeafrefOrIdentityRef(typeDefinition, parentNode);
-        if (returnType != null) {
-            return returnType;
-        }
-
+        // Deal with base types
         if (typeDefinition.getBaseType() == null) {
-            // Now deal with base types
-            returnType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForYangType(typeDefinition.getQName()
-                .getLocalName());
-            if (returnType == null) {
+            // We have to deal with differing handling of decimal64. The old parser used a fixed Decimal64 type
+            // and generated an enclosing ExtendedType to hold any range constraints. The new parser instantiates
+            // a base type which holds these constraints.
+            if (typeDefinition instanceof DecimalTypeDefinition) {
+                final Type ret = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(typeDefinition, parentNode, r);
+                if (ret != null) {
+                    return ret;
+                }
+            }
+
+            // Deal with leafrefs/identityrefs
+            Type ret = javaTypeForLeafrefOrIdentityRef(typeDefinition, parentNode);
+            if (ret != null) {
+                return ret;
+            }
+
+            // FIXME: it looks as though we could be using the same codepath as above...
+            ret = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForYangType(typeDefinition.getQName().getLocalName());
+            if (ret == null) {
                 LOG.debug("Failed to resolve Java type for {}", typeDefinition);
             }
 
-            // FIXME: what about base types with restrictions?
-            return returnType;
+            return ret;
         }
 
-        returnType = javaTypeForExtendedType(typeDefinition);
+        Type returnType = javaTypeForExtendedType(typeDefinition);
         if (r != null && returnType instanceof GeneratedTransferObject) {
-            GeneratedTransferObject gto = (GeneratedTransferObject) returnType;
-            Module module = findParentModule(schemaContext, parentNode);
-            String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
-            String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName,
-                typeDefinition.getPath());
-            String genTOName = BindingMapping.getClassName(typedefName);
-            String name = packageName + "." + genTOName;
+            final GeneratedTransferObject gto = (GeneratedTransferObject) returnType;
+            final Module module = findParentModule(this.schemaContext, parentNode);
+            final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
+            final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, typeDefinition.getPath());
+            final String genTOName = BindingMapping.getClassName(typedefName);
+            final String name = packageName + "." + genTOName;
             if (!(returnType.getFullyQualifiedName().equals(name))) {
                 returnType = shadedTOWithRestrictions(gto, r);
             }
@@ -236,14 +240,14 @@ public final class TypeProviderImpl implements TypeProvider {
     }
 
     private static GeneratedTransferObject shadedTOWithRestrictions(final GeneratedTransferObject gto, final Restrictions r) {
-        GeneratedTOBuilder gtob = new GeneratedTOBuilderImpl(gto.getPackageName(), gto.getName());
-        GeneratedTransferObject parent = gto.getSuperType();
+        final GeneratedTOBuilder gtob = new GeneratedTOBuilderImpl(gto.getPackageName(), gto.getName());
+        final GeneratedTransferObject parent = gto.getSuperType();
         if (parent != null) {
             gtob.setExtendsType(parent);
         }
         gtob.setRestrictions(r);
-        for (GeneratedProperty gp : gto.getProperties()) {
-            GeneratedPropertyBuilder gpb = gtob.addProperty(gp.getName());
+        for (final GeneratedProperty gp : gto.getProperties()) {
+            final GeneratedPropertyBuilder gpb = gtob.addProperty(gp.getName());
             gpb.setValue(gp.getValue());
             gpb.setReadOnly(gp.isReadOnly());
             gpb.setAccessModifier(gp.getAccessModifier());
@@ -269,7 +273,7 @@ public final class TypeProviderImpl implements TypeProvider {
         while (iterator.hasNext() && !isAugmenting) {
             final QName next = iterator.next();
             if (current == null) {
-                dataChildByName = schemaContext.getDataChildByName(next);
+                dataChildByName = this.schemaContext.getDataChildByName(next);
             } else {
                 dataChildByName = current.getDataChildByName(next);
             }
@@ -287,12 +291,12 @@ public final class TypeProviderImpl implements TypeProvider {
         }
         /////
 
-        Module parentModule = getParentModule(parentNode);
+        final Module parentModule = getParentModule(parentNode);
         if (!leafRefStrippedXPath.isAbsolute()) {
-            leafRefValueNode = SchemaContextUtil.findDataSchemaNodeForRelativeXPath(schemaContext, parentModule,
+            leafRefValueNode = SchemaContextUtil.findDataSchemaNodeForRelativeXPath(this.schemaContext, parentModule,
                     parentNode, leafRefStrippedXPath);
         } else {
-            leafRefValueNode = SchemaContextUtil.findDataSchemaNode(schemaContext, parentModule, leafRefStrippedXPath);
+            leafRefValueNode = SchemaContextUtil.findDataSchemaNode(this.schemaContext, parentModule, leafRefStrippedXPath);
         }
         return (leafRefValueNode != null) ? leafRefValueNode.equals(parentNode) : false;
     }
@@ -339,10 +343,10 @@ public final class TypeProviderImpl implements TypeProvider {
                 final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) baseTypeDef;
                 returnType = provideTypeForEnum(enumTypeDef, typedefName, typeDefinition);
             } else {
-                final Module module = findParentModule(schemaContext, typeDefinition);
-                Restrictions r = BindingGeneratorUtil.getRestrictions(typeDefinition);
+                final Module module = findParentModule(this.schemaContext, typeDefinition);
+                final Restrictions r = BindingGeneratorUtil.getRestrictions(typeDefinition);
                 if (module != null) {
-                    final Map<Date, Map<String, Type>> modulesByDate = genTypeDefsContextMap.get(module.getName());
+                    final Map<Date, Map<String, Type>> modulesByDate = this.genTypeDefsContextMap.get(module.getName());
                     final Map<String, Type> genTOs = modulesByDate.get(module.getRevision());
                     if (genTOs != null) {
                         returnType = genTOs.get(typedefName);
@@ -373,11 +377,11 @@ public final class TypeProviderImpl implements TypeProvider {
      *         <code>idref</code>
      */
     private Type provideTypeForIdentityref(final IdentityrefTypeDefinition idref) {
-        QName baseIdQName = idref.getIdentity().getQName();
-        Module module = schemaContext.findModuleByNamespaceAndRevision(baseIdQName.getNamespace(),
+        final QName baseIdQName = idref.getIdentity().getQName();
+        final Module module = this.schemaContext.findModuleByNamespaceAndRevision(baseIdQName.getNamespace(),
                 baseIdQName.getRevision());
         IdentitySchemaNode identity = null;
-        for (IdentitySchemaNode id : module.getIdentities()) {
+        for (final IdentitySchemaNode id : module.getIdentities()) {
             if (id.getQName().equals(baseIdQName)) {
                 identity = id;
             }
@@ -388,8 +392,8 @@ public final class TypeProviderImpl implements TypeProvider {
         final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, identity.getPath());
         final String genTypeName = BindingMapping.getClassName(identity.getQName());
 
-        Type baseType = Types.typeForClass(Class.class);
-        Type paramType = Types.wildcardTypeFor(packageName, genTypeName);
+        final Type baseType = Types.typeForClass(Class.class);
+        final Type paramType = Types.wildcardTypeFor(packageName, genTypeName);
         return Types.parameterizedTypeFor(baseType, paramType);
     }
 
@@ -408,8 +412,7 @@ public final class TypeProviderImpl implements TypeProvider {
      *             <li>if name of <code>typeDefinition</code></li>
      *             </ul>
      */
-    public Type generatedTypeForExtendedDefinitionType(final TypeDefinition<?> typeDefinition,
-            final SchemaNode parentNode) {
+    public Type generatedTypeForExtendedDefinitionType(final TypeDefinition<?> typeDefinition, final SchemaNode parentNode) {
         Preconditions.checkArgument(typeDefinition != null, "Type Definition cannot be NULL!");
         if (typeDefinition.getQName() == null) {
             throw new IllegalArgumentException(
@@ -420,10 +423,10 @@ public final class TypeProviderImpl implements TypeProvider {
 
         final TypeDefinition<?> baseTypeDef = baseTypeDefForExtendedType(typeDefinition);
         if (!(baseTypeDef instanceof LeafrefTypeDefinition) && !(baseTypeDef instanceof IdentityrefTypeDefinition)) {
-            final Module module = findParentModule(schemaContext, parentNode);
+            final Module module = findParentModule(this.schemaContext, parentNode);
 
             if (module != null) {
-                final Map<Date, Map<String, Type>> modulesByDate = genTypeDefsContextMap.get(module.getName());
+                final Map<Date, Map<String, Type>> modulesByDate = this.genTypeDefsContextMap.get(module.getName());
                 final Map<String, Type> genTOs = modulesByDate.get(module.getRevision());
                 if (genTOs != null) {
                     return genTOs.get(typeDefinition.getQName().getLocalName());
@@ -483,30 +486,31 @@ public final class TypeProviderImpl implements TypeProvider {
 
         if (strXPath != null) {
             if (strXPath.indexOf('[') == -1) {
-                final Module module = findParentModule(schemaContext, parentNode);
-                if (module != null) {
-                    final SchemaNode dataNode;
-                    if (xpath.isAbsolute()) {
-                        dataNode = findDataSchemaNode(schemaContext, module, xpath);
-                    } else {
-                        dataNode = findDataSchemaNodeForRelativeXPath(schemaContext, module, parentNode, xpath);
-                    }
+                final Module module = findParentModule(this.schemaContext, parentNode);
+                Preconditions.checkArgument(module != null, "Failed to find module for parent %s", parentNode);
 
-                    if (leafContainsEnumDefinition(dataNode)) {
-                        returnType = referencedTypes.get(dataNode.getPath());
-                    } else if (leafListContainsEnumDefinition(dataNode)) {
-                        returnType = Types.listTypeFor(referencedTypes.get(dataNode.getPath()));
-                    } else {
-                        returnType = resolveTypeFromDataSchemaNode(dataNode);
-                    }
+                final SchemaNode dataNode;
+                if (xpath.isAbsolute()) {
+                    dataNode = findDataSchemaNode(this.schemaContext, module, xpath);
+                } else {
+                    dataNode = findDataSchemaNodeForRelativeXPath(this.schemaContext, module, parentNode, xpath);
+                }
+                Preconditions.checkArgument(dataNode != null, "Failed to find leafref target: %s in module %s (%s)",
+                        strXPath, this.getParentModule(parentNode).getName(), parentNode.getQName().getModule());
+
+                if (leafContainsEnumDefinition(dataNode)) {
+                    returnType = this.referencedTypes.get(dataNode.getPath());
+                } else if (leafListContainsEnumDefinition(dataNode)) {
+                    returnType = Types.listTypeFor(this.referencedTypes.get(dataNode.getPath()));
+                } else {
+                    returnType = resolveTypeFromDataSchemaNode(dataNode);
                 }
             } else {
                 returnType = Types.typeForClass(Object.class);
             }
         }
-        if (returnType == null) {
-            throw new IllegalArgumentException("Failed to find leafref target: " + strXPath);
-        }
+        Preconditions.checkArgument(returnType != null, "Failed to find leafref target: %s in module %s (%s)",
+                strXPath, this.getParentModule(parentNode).getName(), parentNode.getQName().getModule(), this);
         return returnType;
     }
 
@@ -526,7 +530,7 @@ public final class TypeProviderImpl implements TypeProvider {
     private static boolean leafContainsEnumDefinition(final SchemaNode dataNode) {
         if (dataNode instanceof LeafSchemaNode) {
             final LeafSchemaNode leaf = (LeafSchemaNode) dataNode;
-            if (leaf.getType() instanceof EnumTypeDefinition) {
+            if (CompatUtils.compatLeafType(leaf) instanceof EnumTypeDefinition) {
                 return true;
             }
         }
@@ -559,7 +563,7 @@ public final class TypeProviderImpl implements TypeProvider {
 
     /**
      * Converts <code>enumTypeDef</code> to
-     * {@link org.opendaylight.yangtools.sal.binding.model.api.Enumeration
+     * {@link Enumeration
      * enumeration}.
      *
      * @param enumTypeDef
@@ -576,8 +580,7 @@ public final class TypeProviderImpl implements TypeProvider {
      *             <li>if name of <code>enumTypeDef</code> equal null</li>
      *             </ul>
      */
-    private Enumeration provideTypeForEnum(final EnumTypeDefinition enumTypeDef, final String enumName,
-            final SchemaNode parentNode) {
+    private Enumeration provideTypeForEnum(final EnumTypeDefinition enumTypeDef, final String enumName, final SchemaNode parentNode) {
         Preconditions.checkArgument(enumTypeDef != null, "EnumTypeDefinition reference cannot be NULL!");
         Preconditions.checkArgument(enumTypeDef.getValues() != null,
                 "EnumTypeDefinition MUST contain at least ONE value definition!");
@@ -587,11 +590,12 @@ public final class TypeProviderImpl implements TypeProvider {
 
         final String enumerationName = BindingMapping.getClassName(enumName);
 
-        Module module = findParentModule(schemaContext, parentNode);
+        final Module module = findParentModule(this.schemaContext, parentNode);
         final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
 
         final EnumerationBuilderImpl enumBuilder = new EnumerationBuilderImpl(basePackageName, enumerationName);
-        enumBuilder.setDescription(enumTypeDef.getDescription());
+        final String enumTypedefDescription = encodeAngleBrackets(enumTypeDef.getDescription());
+        enumBuilder.setDescription(enumTypedefDescription);
         enumBuilder.setReference(enumTypeDef.getReference());
         enumBuilder.setModuleName(module.getName());
         enumBuilder.setSchemaPath(enumTypeDef.getPath().getPathFromRoot());
@@ -622,8 +626,7 @@ public final class TypeProviderImpl implements TypeProvider {
      *             </ul>
      *
      */
-    private static Enumeration addInnerEnumerationToTypeBuilder(final EnumTypeDefinition enumTypeDef, final String enumName,
-            final GeneratedTypeBuilderBase<?> typeBuilder) {
+    private static Enumeration addInnerEnumerationToTypeBuilder(final EnumTypeDefinition enumTypeDef, final String enumName, final GeneratedTypeBuilderBase<?> typeBuilder) {
         Preconditions.checkArgument(enumTypeDef != null, "EnumTypeDefinition reference cannot be NULL!");
         Preconditions.checkArgument(enumTypeDef.getValues() != null,
                 "EnumTypeDefinition MUST contain at least ONE value definition!");
@@ -635,7 +638,8 @@ public final class TypeProviderImpl implements TypeProvider {
         final String enumerationName = BindingMapping.getClassName(enumName);
 
         final EnumBuilder enumBuilder = typeBuilder.addEnumeration(enumerationName);
-        enumBuilder.setDescription(enumTypeDef.getDescription());
+        final String enumTypedefDescription = encodeAngleBrackets(enumTypeDef.getDescription());
+        enumBuilder.setDescription(enumTypedefDescription);
         enumBuilder.updateEnumPairsFromEnumTypeDef(enumTypeDef);
         return enumBuilder.toInstance(enumBuilder);
     }
@@ -652,7 +656,8 @@ public final class TypeProviderImpl implements TypeProvider {
         if (dataNode != null) {
             if (dataNode instanceof LeafSchemaNode) {
                 final LeafSchemaNode leaf = (LeafSchemaNode) dataNode;
-                returnType = javaTypeForSchemaDefinitionType(leaf.getType(), leaf);
+                final TypeDefinition<?> type = CompatUtils.compatLeafType(leaf);
+                returnType = javaTypeForSchemaDefinitionType(type, leaf);
             } else if (dataNode instanceof LeafListSchemaNode) {
                 final LeafListSchemaNode leafList = (LeafListSchemaNode) dataNode;
                 returnType = javaTypeForSchemaDefinitionType(leafList.getType(), leafList);
@@ -676,23 +681,23 @@ public final class TypeProviderImpl implements TypeProvider {
      *
      */
     private void resolveTypeDefsFromContext() {
-        final Set<Module> modules = schemaContext.getModules();
+        final Set<Module> modules = this.schemaContext.getModules();
         Preconditions.checkArgument(modules != null, "Set of Modules cannot be NULL!");
         final Module[] modulesArray = new Module[modules.size()];
         int i = 0;
-        for (Module modul : modules) {
+        for (final Module modul : modules) {
             modulesArray[i++] = modul;
         }
         final List<Module> modulesSortedByDependency = org.opendaylight.yangtools.yang.parser.util.ModuleDependencySort
                 .sort(modulesArray);
 
         for (final Module module : modulesSortedByDependency) {
-            Map<Date, Map<String, Type>> dateTypeMap = genTypeDefsContextMap.get(module.getName());
+            Map<Date, Map<String, Type>> dateTypeMap = this.genTypeDefsContextMap.get(module.getName());
             if (dateTypeMap == null) {
                 dateTypeMap = new HashMap<>();
             }
             dateTypeMap.put(module.getRevision(), Collections.<String, Type>emptyMap());
-            genTypeDefsContextMap.put(module.getName(), dateTypeMap);
+            this.genTypeDefsContextMap.put(module.getName(), dateTypeMap);
         }
 
         for (final Module module : modulesSortedByDependency) {
@@ -737,8 +742,7 @@ public final class TypeProviderImpl implements TypeProvider {
                     && !(innerTypeDefinition instanceof IdentityrefTypeDefinition)) {
                 Type returnType = null;
                 if (innerTypeDefinition.getBaseType() != null) {
-                    returnType = provideGeneratedTOFromExtendedType(typedef, innerTypeDefinition, basePackageName,
-                            module.getName());
+                    returnType = provideGeneratedTOFromExtendedType(typedef, innerTypeDefinition, basePackageName, module.getName());
                 } else if (innerTypeDefinition instanceof UnionTypeDefinition) {
                     final GeneratedTOBuilder genTOBuilder = provideGeneratedTOBuilderForUnionTypeDef(basePackageName,
                             (UnionTypeDefinition) innerTypeDefinition, typedefName, typedef);
@@ -748,18 +752,18 @@ public final class TypeProviderImpl implements TypeProvider {
                     makeSerializable((GeneratedTOBuilderImpl) genTOBuilder);
                     returnType = genTOBuilder.toInstance();
                     // union builder
-                    GeneratedTOBuilder unionBuilder = new GeneratedTOBuilderImpl(genTOBuilder.getPackageName(),
+                    final GeneratedTOBuilder unionBuilder = new GeneratedTOBuilderImpl(genTOBuilder.getPackageName(),
                             genTOBuilder.getName() + "Builder");
                     unionBuilder.setIsUnionBuilder(true);
-                    MethodSignatureBuilder method = unionBuilder.addMethod("getDefaultInstance");
+                    final MethodSignatureBuilder method = unionBuilder.addMethod("getDefaultInstance");
                     method.setReturnType(returnType);
                     method.addParameter(Types.STRING, "defaultValue");
                     method.setAccessModifier(AccessModifier.PUBLIC);
                     method.setStatic(true);
-                    Set<Type> types = additionalTypes.get(module);
+                    Set<Type> types = this.additionalTypes.get(module);
                     if (types == null) {
                         types = Sets.<Type> newHashSet(unionBuilder.toInstance());
-                        additionalTypes.put(module, types);
+                        this.additionalTypes.put(module, types);
                     } else {
                         types.add(unionBuilder.toInstance());
                     }
@@ -777,12 +781,11 @@ public final class TypeProviderImpl implements TypeProvider {
                     makeSerializable((GeneratedTOBuilderImpl) genTOBuilder);
                     returnType = genTOBuilder.toInstance();
                 } else {
-                    final Type javaType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(
-                            innerTypeDefinition, typedef);
+                    final Type javaType = javaTypeForSchemaDefinitionType(innerTypeDefinition, typedef);
                     returnType = wrapJavaTypeIntoTO(basePackageName, typedef, javaType, module.getName());
                 }
                 if (returnType != null) {
-                    final Map<Date, Map<String, Type>> modulesByDate = genTypeDefsContextMap.get(moduleName);
+                    final Map<Date, Map<String, Type>> modulesByDate = this.genTypeDefsContextMap.get(moduleName);
                     Map<String, Type> typeMap = modulesByDate.get(moduleRevision);
                     if (typeMap != null) {
                         if (typeMap.isEmpty()) {
@@ -809,8 +812,7 @@ public final class TypeProviderImpl implements TypeProvider {
      *            JAVA <code>Type</code> to which is <code>typedef</code> mapped
      * @return generated transfer object which represent<code>javaType</code>
      */
-    private static GeneratedTransferObject wrapJavaTypeIntoTO(final String basePackageName, final TypeDefinition<?> typedef,
-            final Type javaType, final String moduleName) {
+    private static GeneratedTransferObject wrapJavaTypeIntoTO(final String basePackageName, final TypeDefinition<?> typedef, final Type javaType, final String moduleName) {
         Preconditions.checkNotNull(javaType, "javaType cannot be null");
         final String propertyName = "value";
 
@@ -821,6 +823,9 @@ public final class TypeProviderImpl implements TypeProvider {
         genTOBuilder.addEqualsIdentity(genPropBuilder);
         genTOBuilder.addHashIdentity(genPropBuilder);
         genTOBuilder.addToStringProperty(genPropBuilder);
+        if (typedef.getStatus() == Status.DEPRECATED) {
+            genTOBuilder.addAnnotation("", "Deprecated");
+        }
         if (javaType instanceof ConcreteType && "String".equals(javaType.getName()) && typedef.getBaseType() != null) {
             final List<String> regExps = resolveRegExpressionsFromTypedef(typedef);
             addStringRegExAsConstant(genTOBuilder, regExps);
@@ -847,24 +852,16 @@ public final class TypeProviderImpl implements TypeProvider {
      */
     public GeneratedTOBuilder provideGeneratedTOBuilderForUnionTypeDef(final String basePackageName,
             final UnionTypeDefinition typedef, final String typeDefName, final SchemaNode parentNode) {
-        final List<GeneratedTOBuilder> genTOBuilders = provideGeneratedTOBuildersForUnionTypeDef(basePackageName,
+        final List<GeneratedTOBuilder> builders = provideGeneratedTOBuildersForUnionTypeDef(basePackageName,
                 typedef, typeDefName, parentNode);
-        GeneratedTOBuilder resultTOBuilder = null;
-        if (genTOBuilders.isEmpty()) {
-            throw new IllegalStateException("No GeneratedTOBuilder objects generated from union " + typedef);
-        }
+        Preconditions.checkState(!builders.isEmpty(), "No GeneratedTOBuilder objects generated from union %s", typedef);
 
-        resultTOBuilder = genTOBuilders.remove(0);
-        for (GeneratedTOBuilder genTOBuilder : genTOBuilders) {
+        final GeneratedTOBuilder resultTOBuilder = builders.remove(0);
+        for (final GeneratedTOBuilder genTOBuilder : builders) {
             resultTOBuilder.addEnclosingTransferObject(genTOBuilder);
         }
 
-        final GeneratedPropertyBuilder genPropBuilder = resultTOBuilder.addProperty("value");
-        genPropBuilder.setReturnType(Types.CHAR_ARRAY);
-        resultTOBuilder.addEqualsIdentity(genPropBuilder);
-        resultTOBuilder.addHashIdentity(genPropBuilder);
-        resultTOBuilder.addToStringProperty(genPropBuilder);
-
+        resultTOBuilder.addProperty("value").setReturnType(Types.CHAR_ARRAY);
         return resultTOBuilder;
     }
 
@@ -896,13 +893,14 @@ public final class TypeProviderImpl implements TypeProvider {
 
         final List<GeneratedTOBuilder> generatedTOBuilders = new ArrayList<>();
         final List<TypeDefinition<?>> unionTypes = typedef.getTypes();
-        final Module module = findParentModule(schemaContext, parentNode);
+        final Module module = findParentModule(this.schemaContext, parentNode);
 
         final GeneratedTOBuilderImpl unionGenTOBuilder;
         if (typeDefName != null && !typeDefName.isEmpty()) {
             final String typeName = BindingMapping.getClassName(typeDefName);
             unionGenTOBuilder = new GeneratedTOBuilderImpl(basePackageName, typeName);
-            unionGenTOBuilder.setDescription(typedef.getDescription());
+            final String typedefDescription = encodeAngleBrackets(typedef.getDescription());
+            unionGenTOBuilder.setDescription(typedefDescription);
             unionGenTOBuilder.setReference(typedef.getReference());
             unionGenTOBuilder.setSchemaPath(typedef.getPath().getPathFromRoot());
             unionGenTOBuilder.setModuleName(module.getName());
@@ -915,19 +913,18 @@ public final class TypeProviderImpl implements TypeProvider {
         final List<String> regularExpressions = new ArrayList<String>();
         for (final TypeDefinition<?> unionType : unionTypes) {
             final String unionTypeName = unionType.getQName().getLocalName();
-            if (unionType instanceof UnionType) {
-                generatedTOBuilders.addAll(resolveUnionSubtypeAsUnion(unionGenTOBuilder, (UnionType) unionType,
-                        basePackageName, parentNode));
-            } else if (unionType instanceof ExtendedType) {
-                resolveExtendedSubtypeAsUnion(unionGenTOBuilder, (ExtendedType) unionType, regularExpressions,
+            if (unionType.getBaseType() != null) {
+                resolveExtendedSubtypeAsUnion(unionGenTOBuilder, unionType, regularExpressions,
                         parentNode);
+            } else if (unionType instanceof UnionTypeDefinition) {
+                generatedTOBuilders.addAll(resolveUnionSubtypeAsUnion(unionGenTOBuilder, (UnionTypeDefinition) unionType,
+                        basePackageName, parentNode));
             } else if (unionType instanceof EnumTypeDefinition) {
                 final Enumeration enumeration = addInnerEnumerationToTypeBuilder((EnumTypeDefinition) unionType,
                         unionTypeName, unionGenTOBuilder);
                 updateUnionTypeAsProperty(unionGenTOBuilder, enumeration, unionTypeName);
             } else {
-                final Type javaType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(unionType,
-                        parentNode);
+                final Type javaType = javaTypeForSchemaDefinitionType(unionType, parentNode);
                 updateUnionTypeAsProperty(unionGenTOBuilder, javaType, unionTypeName);
             }
         }
@@ -946,8 +943,7 @@ public final class TypeProviderImpl implements TypeProvider {
      *
      * In this case the new generated TO is created for union subtype (recursive
      * call of method
-     * {@link #provideGeneratedTOBuildersForUnionTypeDef(String, UnionTypeDefinition,
-     * String, SchemaNode)}
+     * {@link #provideGeneratedTOBuildersForUnionTypeDef(String, UnionTypeDefinition, String, SchemaNode)}
      * provideGeneratedTOBuilderForUnionTypeDef} and in parent TO builder
      * <code>parentUnionGenTOBuilder</code> is created property which type is
      * equal to new generated TO.
@@ -998,7 +994,7 @@ public final class TypeProviderImpl implements TypeProvider {
      *
      */
     private void resolveExtendedSubtypeAsUnion(final GeneratedTOBuilder parentUnionGenTOBuilder,
-            final ExtendedType unionSubtype, final List<String> regularExpressions, final SchemaNode parentNode) {
+            final TypeDefinition<?> unionSubtype, final List<String> regularExpressions, final SchemaNode parentNode) {
         final String unionTypeName = unionSubtype.getQName().getLocalName();
         final Type genTO = findGenTO(unionTypeName, unionSubtype);
         if (genTO != null) {
@@ -1006,13 +1002,28 @@ public final class TypeProviderImpl implements TypeProvider {
         } else {
             final TypeDefinition<?> baseType = baseTypeDefForExtendedType(unionSubtype);
             if (unionTypeName.equals(baseType.getQName().getLocalName())) {
-                final Type javaType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(baseType,
-                        parentNode);
+                final Type javaType =
+                        BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(baseType, parentNode);
                 if (javaType != null) {
                     updateUnionTypeAsProperty(parentUnionGenTOBuilder, javaType, unionTypeName);
                 }
+            } else if (baseType instanceof LeafrefTypeDefinition) {
+                final Type javaType = javaTypeForSchemaDefinitionType(baseType, parentNode);
+                boolean typeExist = false;
+                for (final GeneratedPropertyBuilder generatedPropertyBuilder : parentUnionGenTOBuilder
+                        .getProperties()) {
+                    final Type origType = ((GeneratedPropertyBuilderImpl) generatedPropertyBuilder).getReturnType();
+                    if (origType != null && javaType != null && javaType == origType) {
+                        typeExist = true;
+                        break;
+                    }
+                }
+                if (!typeExist && javaType != null) {
+                    updateUnionTypeAsProperty(parentUnionGenTOBuilder, javaType, new StringBuilder(javaType.getName())
+                            .append(parentUnionGenTOBuilder.getName()).append("Value").toString());
+                }
             }
-            if (baseType instanceof StringType) {
+            if (baseType instanceof StringTypeDefinition) {
                 regularExpressions.addAll(resolveRegExpressionsFromTypedef(unionSubtype));
             }
         }
@@ -1028,9 +1039,9 @@ public final class TypeProviderImpl implements TypeProvider {
      *         <code>null</code> it it doesn't exist
      */
     private Type findGenTO(final String searchedTypeName, final SchemaNode parentNode) {
-        final Module typeModule = findParentModule(schemaContext, parentNode);
+        final Module typeModule = findParentModule(this.schemaContext, parentNode);
         if (typeModule != null && typeModule.getName() != null) {
-            final Map<Date, Map<String, Type>> modulesByDate = genTypeDefsContextMap.get(typeModule.getName());
+            final Map<Date, Map<String, Type>> modulesByDate = this.genTypeDefsContextMap.get(typeModule.getName());
             final Map<String, Type> genTOs = modulesByDate.get(typeModule.getRevision());
             if (genTOs != null) {
                 return genTOs.get(searchedTypeName);
@@ -1050,14 +1061,12 @@ public final class TypeProviderImpl implements TypeProvider {
      *            generated TO builder which is converted to generated TO and
      *            stored
      */
-    private void storeGenTO(final TypeDefinition<?> newTypeDef, final GeneratedTOBuilder genTOBuilder,
-            final SchemaNode parentNode) {
-        if (!(newTypeDef instanceof UnionType)) {
-
-            final Module parentModule = findParentModule(schemaContext, parentNode);
+    private void storeGenTO(final TypeDefinition<?> newTypeDef, final GeneratedTOBuilder genTOBuilder, final SchemaNode parentNode) {
+        if (!(newTypeDef instanceof UnionTypeDefinition)) {
+            final Module parentModule = findParentModule(this.schemaContext, parentNode);
             if (parentModule != null && parentModule.getName() != null) {
-                Map<Date, Map<String, Type>> modulesByDate = genTypeDefsContextMap.get(parentModule.getName());
-                Map<String, Type> genTOsMap = modulesByDate.get(parentModule.getRevision());
+                final Map<Date, Map<String, Type>> modulesByDate = this.genTypeDefsContextMap.get(parentModule.getName());
+                final Map<String, Type> genTOsMap = modulesByDate.get(parentModule.getRevision());
                 genTOsMap.put(newTypeDef.getQName().getLocalName(), genTOBuilder.toInstance());
             }
         }
@@ -1065,7 +1074,7 @@ public final class TypeProviderImpl implements TypeProvider {
 
     /**
      * Adds a new property with the name <code>propertyName</code> and with type
-     * <code>type</code> to <code>unonGenTransObject</code>.
+     * <code>type</code> to <code>unionGenTransObject</code>.
      *
      * @param unionGenTransObject
      *            generated TO to which should be property added
@@ -1076,8 +1085,7 @@ public final class TypeProviderImpl implements TypeProvider {
      *            string with name of property which should be added to
      *            <code>unionGentransObject</code>
      */
-    private static void updateUnionTypeAsProperty(final GeneratedTOBuilder unionGenTransObject, final Type type,
-            final String propertyName) {
+    private static void updateUnionTypeAsProperty(final GeneratedTOBuilder unionGenTransObject, final Type type, final String propertyName) {
         if (unionGenTransObject != null && type != null && !unionGenTransObject.containsProperty(propertyName)) {
             final GeneratedPropertyBuilder propBuilder = unionGenTransObject
                     .addProperty(BindingMapping.getPropertyName(propertyName));
@@ -1099,8 +1107,7 @@ public final class TypeProviderImpl implements TypeProvider {
      * @return generated TO builder which contains data from
      *         <code>typedef</code> and <code>basePackageName</code>
      */
-    private static GeneratedTOBuilderImpl typedefToTransferObject(final String basePackageName,
-            final TypeDefinition<?> typedef, final String moduleName) {
+    private static GeneratedTOBuilderImpl typedefToTransferObject(final String basePackageName, final TypeDefinition<?> typedef, final String moduleName) {
 
         final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, typedef.getPath());
         final String typeDefTOName = typedef.getQName().getLocalName();
@@ -1108,8 +1115,9 @@ public final class TypeProviderImpl implements TypeProvider {
         if ((packageName != null) && (typeDefTOName != null)) {
             final String genTOName = BindingMapping.getClassName(typeDefTOName);
             final GeneratedTOBuilderImpl newType = new GeneratedTOBuilderImpl(packageName, genTOName);
+            final String typedefDescription = encodeAngleBrackets(typedef.getDescription());
 
-            newType.setDescription(typedef.getDescription());
+            newType.setDescription(typedefDescription);
             newType.setReference(typedef.getReference());
             newType.setSchemaPath(typedef.getPath().getPathFromRoot());
             newType.setModuleName(moduleName);
@@ -1139,19 +1147,19 @@ public final class TypeProviderImpl implements TypeProvider {
      *             <li>if <code>basePackageName</code> equals null</li>
      *             </ul>
      */
-    public GeneratedTOBuilder provideGeneratedTOBuilderForBitsTypeDefinition(final String basePackageName,
-            final TypeDefinition<?> typeDef, final String typeDefName, final String moduleName) {
+    public GeneratedTOBuilder provideGeneratedTOBuilderForBitsTypeDefinition(final String basePackageName, final TypeDefinition<?> typeDef, final String typeDefName, final String moduleName) {
 
         Preconditions.checkArgument(typeDef != null, "typeDef cannot be NULL!");
         Preconditions.checkArgument(basePackageName != null, "Base Package Name cannot be NULL!");
 
         if (typeDef instanceof BitsTypeDefinition) {
-            BitsTypeDefinition bitsTypeDefinition = (BitsTypeDefinition) typeDef;
+            final BitsTypeDefinition bitsTypeDefinition = (BitsTypeDefinition) typeDef;
 
             final String typeName = BindingMapping.getClassName(typeDefName);
             final GeneratedTOBuilderImpl genTOBuilder = new GeneratedTOBuilderImpl(basePackageName, typeName);
+            final String typedefDescription = encodeAngleBrackets(typeDef.getDescription());
 
-            genTOBuilder.setDescription(typeDef.getDescription());
+            genTOBuilder.setDescription(typedefDescription);
             genTOBuilder.setReference(typeDef.getReference());
             genTOBuilder.setSchemaPath(typeDef.getPath().getPathFromRoot());
             genTOBuilder.setModuleName(moduleName);
@@ -1160,7 +1168,7 @@ public final class TypeProviderImpl implements TypeProvider {
             final List<Bit> bitList = bitsTypeDefinition.getBits();
             GeneratedPropertyBuilder genPropertyBuilder;
             for (final Bit bit : bitList) {
-                String name = bit.getName();
+                final String name = bit.getName();
                 genPropertyBuilder = genTOBuilder.addProperty(BindingMapping.getPropertyName(name));
                 genPropertyBuilder.setReadOnly(true);
                 genPropertyBuilder.setReturnType(BaseYangTypes.BOOLEAN_TYPE);
@@ -1190,14 +1198,7 @@ public final class TypeProviderImpl implements TypeProvider {
         Preconditions.checkArgument(typedef != null, "typedef can't be null");
 
         final List<PatternConstraint> patternConstraints;
-        if (typedef instanceof ExtendedType) {
-            final TypeDefinition<?> strTypeDef = baseTypeDefForExtendedType(typedef);
-            if (strTypeDef instanceof StringType) {
-                patternConstraints = ((ExtendedType)typedef).getPatternConstraints();
-            } else {
-                patternConstraints = ImmutableList.of();
-            }
-        } else if (typedef instanceof StringTypeDefinition) {
+        if (typedef instanceof StringTypeDefinition) {
             // FIXME: run diff against base
             patternConstraints = ((StringTypeDefinition) typedef).getPatternConstraints();
         } else {
@@ -1205,7 +1206,7 @@ public final class TypeProviderImpl implements TypeProvider {
         }
 
         final List<String> regExps = new ArrayList<>(patternConstraints.size());
-        for (PatternConstraint patternConstraint : patternConstraints) {
+        for (final PatternConstraint patternConstraint : patternConstraints) {
             final String regEx = patternConstraint.getRegularExpression();
             final String modifiedRegEx = StringEscapeUtils.escapeJava(regEx);
             regExps.add(modifiedRegEx);
@@ -1270,8 +1271,7 @@ public final class TypeProviderImpl implements TypeProvider {
      *             <li>if <code>typedefName</code> equals null</li>
      *             </ul>
      */
-    private GeneratedTransferObject provideGeneratedTOFromExtendedType(final TypeDefinition<?> typedef,
-            final TypeDefinition<?> innerExtendedType, final String basePackageName, final String moduleName) {
+    private GeneratedTransferObject provideGeneratedTOFromExtendedType(final TypeDefinition<?> typedef, final TypeDefinition<?> innerExtendedType, final String basePackageName, final String moduleName) {
         Preconditions.checkArgument(innerExtendedType != null, "Extended type cannot be NULL!");
         Preconditions.checkArgument(basePackageName != null, "String with base package name cannot be NULL!");
 
@@ -1279,14 +1279,18 @@ public final class TypeProviderImpl implements TypeProvider {
         final String classTypedefName = BindingMapping.getClassName(typedefName);
         final String innerTypeDef = innerExtendedType.getQName().getLocalName();
         final GeneratedTOBuilderImpl genTOBuilder = new GeneratedTOBuilderImpl(basePackageName, classTypedefName);
+        final String typedefDescription = encodeAngleBrackets(typedef.getDescription());
 
-        genTOBuilder.setDescription(typedef.getDescription());
+        genTOBuilder.setDescription(typedefDescription);
         genTOBuilder.setReference(typedef.getReference());
         genTOBuilder.setSchemaPath(typedef.getPath().getPathFromRoot());
         genTOBuilder.setModuleName(moduleName);
         genTOBuilder.setTypedef(true);
-        Restrictions r = BindingGeneratorUtil.getRestrictions(typedef);
+        final Restrictions r = BindingGeneratorUtil.getRestrictions(typedef);
         genTOBuilder.setRestrictions(r);
+        if (typedef.getStatus() == Status.DEPRECATED) {
+            genTOBuilder.addAnnotation("", "Deprecated");
+        }
 
         if (baseTypeDefForExtendedType(innerExtendedType) instanceof UnionTypeDefinition) {
             genTOBuilder.setIsUnion(true);
@@ -1294,14 +1298,14 @@ public final class TypeProviderImpl implements TypeProvider {
 
         Map<Date, Map<String, Type>> modulesByDate = null;
         Map<String, Type> typeMap = null;
-        final Module parentModule = findParentModule(schemaContext, innerExtendedType);
+        final Module parentModule = findParentModule(this.schemaContext, innerExtendedType);
         if (parentModule != null) {
-            modulesByDate = genTypeDefsContextMap.get(parentModule.getName());
+            modulesByDate = this.genTypeDefsContextMap.get(parentModule.getName());
             typeMap = modulesByDate.get(parentModule.getRevision());
         }
 
         if (typeMap != null) {
-            Type type = typeMap.get(innerTypeDef);
+            final Type type = typeMap.get(innerTypeDef);
             if (type instanceof GeneratedTransferObject) {
                 genTOBuilder.setExtendsType((GeneratedTransferObject) type);
             }
@@ -1321,7 +1325,7 @@ public final class TypeProviderImpl implements TypeProvider {
      */
     private static void makeSerializable(final GeneratedTOBuilderImpl gto) {
         gto.addImplementsType(Types.typeForClass(Serializable.class));
-        GeneratedPropertyBuilder prop = new GeneratedPropertyBuilderImpl("serialVersionUID");
+        final GeneratedPropertyBuilder prop = new GeneratedPropertyBuilderImpl("serialVersionUID");
         prop.setValue(Long.toString(BindingGeneratorUtil.computeDefaultSUID(gto)));
         gto.setSUID(prop);
     }
@@ -1342,10 +1346,10 @@ public final class TypeProviderImpl implements TypeProvider {
      */
     private static List<TypeDefinition<?>> sortTypeDefinitionAccordingDepth(
             final Collection<TypeDefinition<?>> unsortedTypeDefinitions) {
-        List<TypeDefinition<?>> sortedTypeDefinition = new ArrayList<>();
+        final List<TypeDefinition<?>> sortedTypeDefinition = new ArrayList<>();
 
-        Map<Integer, List<TypeDefinition<?>>> typeDefinitionsDepths = new TreeMap<>();
-        for (TypeDefinition<?> unsortedTypeDefinition : unsortedTypeDefinitions) {
+        final Map<Integer, List<TypeDefinition<?>>> typeDefinitionsDepths = new TreeMap<>();
+        for (final TypeDefinition<?> unsortedTypeDefinition : unsortedTypeDefinitions) {
             final int depth = getTypeDefinitionDepth(unsortedTypeDefinition);
             List<TypeDefinition<?>> typeDefinitionsConcreteDepth = typeDefinitionsDepths.get(depth);
             if (typeDefinitionsConcreteDepth == null) {
@@ -1356,7 +1360,7 @@ public final class TypeProviderImpl implements TypeProvider {
         }
 
         // SortedMap guarantees order corresponding to keys in ascending order
-        for (List<TypeDefinition<?>> v : typeDefinitionsDepths.values()) {
+        for (final List<TypeDefinition<?>> v : typeDefinitionsDepths.values()) {
             sortedTypeDefinition.addAll(v);
         }
 
@@ -1373,20 +1377,23 @@ public final class TypeProviderImpl implements TypeProvider {
      *         definition to the base type
      */
     private static int getTypeDefinitionDepth(final TypeDefinition<?> typeDefinition) {
-        // FIXME: rewrite this in a non-recursive manner, without ExtendedType and UnionType
+        // FIXME: rewrite this in a non-recursive manner
         if (typeDefinition == null) {
             return 1;
         }
-        int depth = 1;
-        TypeDefinition<?> baseType = typeDefinition.getBaseType();
+        final TypeDefinition<?> baseType = typeDefinition.getBaseType();
+        if (baseType == null) {
+            return 1;
+        }
 
-        if (baseType instanceof ExtendedType) {
-            depth = depth + getTypeDefinitionDepth(typeDefinition.getBaseType());
-        } else if (baseType instanceof UnionType) {
-            List<TypeDefinition<?>> childTypeDefinitions = ((UnionType) baseType).getTypes();
+        int depth = 1;
+        if (baseType.getBaseType() != null) {
+            depth = depth + getTypeDefinitionDepth(baseType);
+        } else if (baseType instanceof UnionTypeDefinition) {
+            final List<TypeDefinition<?>> childTypeDefinitions = ((UnionTypeDefinition) baseType).getTypes();
             int maxChildDepth = 0;
             int childDepth = 1;
-            for (TypeDefinition<?> childTypeDefinition : childTypeDefinitions) {
+            for (final TypeDefinition<?> childTypeDefinition : childTypeDefinitions) {
                 childDepth = childDepth + getTypeDefinitionDepth(childTypeDefinition);
                 if (childDepth > maxChildDepth) {
                     maxChildDepth = childDepth;
@@ -1407,7 +1414,7 @@ public final class TypeProviderImpl implements TypeProvider {
      * @return string with the number suffix incremented by one (or 1 is added)
      */
     private static String provideAvailableNameForGenTOBuilder(final String name) {
-        Matcher mtch = NUMBERS_PATTERN.matcher(name);
+        final Matcher mtch = NUMBERS_PATTERN.matcher(name);
         if (mtch.find()) {
             final int newSuffix = Integer.valueOf(name.substring(mtch.start())) + 1;
             return name.substring(0, mtch.start()) + newSuffix;
@@ -1419,7 +1426,7 @@ public final class TypeProviderImpl implements TypeProvider {
     public static void addUnitsToGenTO(final GeneratedTOBuilder to, final String units) {
         if (!Strings.isNullOrEmpty(units)) {
             to.addConstant(Types.STRING, "_UNITS", "\"" + units + "\"");
-            GeneratedPropertyBuilder prop = new GeneratedPropertyBuilderImpl("UNITS");
+            final GeneratedPropertyBuilder prop = new GeneratedPropertyBuilderImpl("UNITS");
             prop.setReturnType(Types.STRING);
             to.addToStringProperty(prop);
         }
@@ -1431,34 +1438,34 @@ public final class TypeProviderImpl implements TypeProvider {
     }
 
     public String getTypeDefaultConstruction(final LeafSchemaNode node, final String defaultValue) {
-        TypeDefinition<?> type = node.getType();
-        QName typeQName = type.getQName();
-        TypeDefinition<?> base = baseTypeDefForExtendedType(type);
+        final TypeDefinition<?> type = CompatUtils.compatLeafType(node);
+        final QName typeQName = type.getQName();
+        final TypeDefinition<?> base = baseTypeDefForExtendedType(type);
         Preconditions.checkNotNull(type, "Cannot provide default construction for null type of %s", node);
         Preconditions.checkNotNull(defaultValue, "Cannot provide default construction for null default statement of %s",
                 node);
 
-        StringBuilder sb = new StringBuilder();
+        final StringBuilder sb = new StringBuilder();
         String result = null;
         if (base instanceof BinaryTypeDefinition) {
             result = binaryToDef(defaultValue);
         } else if (base instanceof BitsTypeDefinition) {
             String parentName;
             String className;
-            Module parent = getParentModule(node);
-            Iterator<QName> path = node.getPath().getPathFromRoot().iterator();
+            final Module parent = getParentModule(node);
+            final Iterator<QName> path = node.getPath().getPathFromRoot().iterator();
             path.next();
             if (!(path.hasNext())) {
                 parentName = BindingMapping.getClassName(parent.getName()) + "Data";
-                String basePackageName = BindingMapping.getRootPackageName(parent.getQNameModule());
+                final String basePackageName = BindingMapping.getRootPackageName(parent.getQNameModule());
                 className = basePackageName + "." + parentName + "." + BindingMapping.getClassName(node.getQName());
             } else {
-                String basePackageName = BindingMapping.getRootPackageName(parent.getQNameModule());
-                String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, type.getPath());
+                final String basePackageName = BindingMapping.getRootPackageName(parent.getQNameModule());
+                final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, type.getPath());
                 parentName = BindingMapping.getClassName(parent.getName());
                 className = packageName + "." + parentName + "." + BindingMapping.getClassName(node.getQName());
             }
-            result = bitsToDef((BitsTypeDefinition) base, className, defaultValue, type instanceof ExtendedType);
+            result = bitsToDef((BitsTypeDefinition) base, className, defaultValue, type.getBaseType() != null);
         } else if (base instanceof BooleanTypeDefinition) {
             result = typeToDef(Boolean.class, defaultValue);
         } else if (base instanceof DecimalTypeDefinition) {
@@ -1466,20 +1473,20 @@ public final class TypeProviderImpl implements TypeProvider {
         } else if (base instanceof EmptyTypeDefinition) {
             result = typeToDef(Boolean.class, defaultValue);
         } else if (base instanceof EnumTypeDefinition) {
-            char[] defValArray = defaultValue.toCharArray();
-            char first = Character.toUpperCase(defaultValue.charAt(0));
+            final char[] defValArray = defaultValue.toCharArray();
+            final char first = Character.toUpperCase(defaultValue.charAt(0));
             defValArray[0] = first;
-            String newDefVal = new String(defValArray);
+            final String newDefVal = new String(defValArray);
             String className;
-            if (type instanceof ExtendedType) {
-                Module m = getParentModule(type);
-                String basePackageName = BindingMapping.getRootPackageName(m.getQNameModule());
-                String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, type.getPath());
+            if (type.getBaseType() != null) {
+                final Module m = getParentModule(type);
+                final String basePackageName = BindingMapping.getRootPackageName(m.getQNameModule());
+                final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, type.getPath());
                 className = packageName + "." + BindingMapping.getClassName(typeQName);
             } else {
-                Module parentModule = getParentModule(node);
-                String basePackageName = BindingMapping.getRootPackageName(parentModule.getQNameModule());
-                String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, node.getPath());
+                final Module parentModule = getParentModule(node);
+                final String basePackageName = BindingMapping.getRootPackageName(parentModule.getQNameModule());
+                final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, node.getPath());
                 className = packageName + "." + BindingMapping.getClassName(node.getQName());
             }
             result = className + "." + newDefVal;
@@ -1487,25 +1494,25 @@ public final class TypeProviderImpl implements TypeProvider {
             throw new UnsupportedOperationException("Cannot get default construction for identityref type");
         } else if (base instanceof InstanceIdentifierTypeDefinition) {
             throw new UnsupportedOperationException("Cannot get default construction for instance-identifier type");
-        } else if (base instanceof Int8) {
+        } else if (BaseTypes.isInt8(base)) {
             result = typeToDef(Byte.class, defaultValue);
-        } else if (base instanceof Int16) {
+        } else if (BaseTypes.isInt16(base)) {
             result = typeToDef(Short.class, defaultValue);
-        } else if (base instanceof Int32) {
+        } else if (BaseTypes.isInt32(base)) {
             result = typeToDef(Integer.class, defaultValue);
-        } else if (base instanceof Int64) {
+        } else if (BaseTypes.isInt64(base)) {
             result = typeToDef(Long.class, defaultValue);
         } else if (base instanceof LeafrefTypeDefinition) {
             result = leafrefToDef(node, (LeafrefTypeDefinition) base, defaultValue);
         } else if (base instanceof StringTypeDefinition) {
             result = "\"" + defaultValue + "\"";
-        } else if (base instanceof Uint8) {
+        } else if (BaseTypes.isUint8(base)) {
             result = typeToDef(Short.class, defaultValue);
-        } else if (base instanceof Uint16) {
+        } else if (BaseTypes.isUint16(base)) {
             result = typeToDef(Integer.class, defaultValue);
-        } else if (base instanceof Uint32) {
+        } else if (BaseTypes.isUint32(base)) {
             result = typeToDef(Long.class, defaultValue);
-        } else if (base instanceof Uint64) {
+        } else if (BaseTypes.isUint64(base)) {
             result = typeToDef(BigInteger.class, defaultValue);
         } else if (base instanceof UnionTypeDefinition) {
             result = unionToDef(node);
@@ -1514,12 +1521,12 @@ public final class TypeProviderImpl implements TypeProvider {
         }
         sb.append(result);
 
-        if (type instanceof ExtendedType && !(base instanceof LeafrefTypeDefinition)
-                && !(base instanceof EnumerationType) && !(base instanceof UnionTypeDefinition)) {
-            Module m = getParentModule(type);
-            String basePackageName = BindingMapping.getRootPackageName(m.getQNameModule());
-            String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, type.getPath());
-            String className = packageName + "." + BindingMapping.getClassName(typeQName);
+        if (type.getBaseType() != null && !(base instanceof LeafrefTypeDefinition)
+                && !(base instanceof EnumTypeDefinition) && !(base instanceof UnionTypeDefinition)) {
+            final Module m = getParentModule(type);
+            final String basePackageName = BindingMapping.getRootPackageName(m.getQNameModule());
+            final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, type.getPath());
+            final String className = packageName + "." + BindingMapping.getClassName(typeQName);
             sb.insert(0, "new " + className + "(");
             sb.insert(sb.length(), ')');
         }
@@ -1532,9 +1539,9 @@ public final class TypeProviderImpl implements TypeProvider {
     }
 
     private static String binaryToDef(final String defaultValue) {
-        StringBuilder sb = new StringBuilder();
-        BaseEncoding en = BaseEncoding.base64();
-        byte[] encoded = en.decode(defaultValue);
+        final StringBuilder sb = new StringBuilder();
+        final BaseEncoding en = BaseEncoding.base64();
+        final byte[] encoded = en.decode(defaultValue);
         sb.append("new byte[] {");
         for (int i = 0; i < encoded.length; i++) {
             sb.append(encoded[i]);
@@ -1546,18 +1553,12 @@ public final class TypeProviderImpl implements TypeProvider {
         return sb.toString();
     }
 
-    private static final Comparator<Bit> BIT_NAME_COMPARATOR = new Comparator<Bit>() {
-        @Override
-        public int compare(final Bit o1, final Bit o2) {
-            return o1.getName().compareTo(o2.getName());
-        }
-    };
+    private static final Comparator<Bit> BIT_NAME_COMPARATOR = (o1, o2) -> o1.getName().compareTo(o2.getName());
 
-    private static String bitsToDef(final BitsTypeDefinition type, final String className, final String defaultValue,
-            final boolean isExt) {
-        List<Bit> bits = new ArrayList<>(type.getBits());
+    private static String bitsToDef(final BitsTypeDefinition type, final String className, final String defaultValue, final boolean isExt) {
+        final List<Bit> bits = new ArrayList<>(type.getBits());
         Collections.sort(bits, BIT_NAME_COMPARATOR);
-        StringBuilder sb = new StringBuilder();
+        final StringBuilder sb = new StringBuilder();
         if (!isExt) {
             sb.append("new ");
             sb.append(className);
@@ -1580,10 +1581,10 @@ public final class TypeProviderImpl implements TypeProvider {
     }
 
     private Module getParentModule(final SchemaNode node) {
-        QName qname = node.getPath().getPathFromRoot().iterator().next();
-        URI namespace = qname.getNamespace();
-        Date revision = qname.getRevision();
-        return schemaContext.findModuleByNamespaceAndRevision(namespace, revision);
+        final QName qname = node.getPath().getPathFromRoot().iterator().next();
+        final URI namespace = qname.getNamespace();
+        final Date revision = qname.getRevision();
+        return this.schemaContext.findModuleByNamespaceAndRevision(namespace, revision);
     }
 
     private String leafrefToDef(final LeafSchemaNode parentNode, final LeafrefTypeDefinition leafrefType, final String defaultValue) {
@@ -1596,15 +1597,15 @@ public final class TypeProviderImpl implements TypeProvider {
 
         if (strXPath != null) {
             if (strXPath.indexOf('[') == -1) {
-                final Module module = findParentModule(schemaContext, parentNode);
+                final Module module = findParentModule(this.schemaContext, parentNode);
                 if (module != null) {
                     final SchemaNode dataNode;
                     if (xpath.isAbsolute()) {
-                        dataNode = findDataSchemaNode(schemaContext, module, xpath);
+                        dataNode = findDataSchemaNode(this.schemaContext, module, xpath);
                     } else {
-                        dataNode = findDataSchemaNodeForRelativeXPath(schemaContext, module, parentNode, xpath);
+                        dataNode = findDataSchemaNodeForRelativeXPath(this.schemaContext, module, parentNode, xpath);
                     }
-                    String result = getTypeDefaultConstruction((LeafSchemaNode) dataNode, defaultValue);
+                    final String result = getTypeDefaultConstruction((LeafSchemaNode) dataNode, defaultValue);
                     return result;
                 }
             } else {
@@ -1616,54 +1617,48 @@ public final class TypeProviderImpl implements TypeProvider {
     }
 
     private String unionToDef(final LeafSchemaNode node) {
+        final TypeDefinition<?> type = CompatUtils.compatLeafType(node);
         String parentName;
         String className;
 
-        if (node.getType() instanceof ExtendedType) {
-            ExtendedType type = (ExtendedType) node.getType();
-            QName typeQName = type.getQName();
+        if (type.getBaseType() != null) {
+            final QName typeQName = type.getQName();
             Module module = null;
-            Set<Module> modules = schemaContext.findModuleByNamespace(typeQName.getNamespace());
+            final Set<Module> modules = this.schemaContext.findModuleByNamespace(typeQName.getNamespace());
             if (modules.size() > 1) {
-                for (Module m : modules) {
+                for (final Module m : modules) {
                     if (m.getRevision().equals(typeQName.getRevision())) {
                         module = m;
                         break;
                     }
                 }
                 if (module == null) {
-                    List<Module> modulesList = new ArrayList<>(modules);
-                    Collections.sort(modulesList, new Comparator<Module>() {
-                        @Override
-                        public int compare(final Module o1, final Module o2) {
-                            return o1.getRevision().compareTo(o2.getRevision());
-                        }
-                    });
+                    final List<Module> modulesList = new ArrayList<>(modules);
+                    Collections.sort(modulesList, (o1, o2) -> o1.getRevision().compareTo(o2.getRevision()));
                     module = modulesList.get(0);
                 }
             } else {
                 module = modules.iterator().next();
             }
 
-            String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
+            final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
             className = basePackageName + "." + BindingMapping.getClassName(typeQName);
         } else {
-            Iterator<QName> path = node.getPath().getPathFromRoot().iterator();
-            QName first = path.next();
+            final Iterator<QName> path = node.getPath().getPathFromRoot().iterator();
+            final QName first = path.next();
             if (!(path.hasNext())) {
-                URI namespace = first.getNamespace();
-                Date revision = first.getRevision();
-                Module parent = schemaContext.findModuleByNamespaceAndRevision(namespace, revision);
+                final URI namespace = first.getNamespace();
+                final Date revision = first.getRevision();
+                final Module parent = this.schemaContext.findModuleByNamespaceAndRevision(namespace, revision);
                 parentName = BindingMapping.getClassName((parent).getName()) + "Data";
-                String basePackageName = BindingMapping.getRootPackageName(parent.getQNameModule());
+                final String basePackageName = BindingMapping.getRootPackageName(parent.getQNameModule());
                 className = basePackageName + "." + parentName + "." + BindingMapping.getClassName(node.getQName());
             } else {
-                URI namespace = first.getNamespace();
-                Date revision = first.getRevision();
-                Module parentModule = schemaContext.findModuleByNamespaceAndRevision(namespace, revision);
-                String basePackageName = BindingMapping.getRootPackageName(parentModule.getQNameModule());
-                String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName,
-                    node.getType().getPath());
+                final URI namespace = first.getNamespace();
+                final Date revision = first.getRevision();
+                final Module parentModule = this.schemaContext.findModuleByNamespaceAndRevision(namespace, revision);
+                final String basePackageName = BindingMapping.getRootPackageName(parentModule.getQNameModule());
+                final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, UNION_PATH);
                 className = packageName + "." + BindingMapping.getClassName(node.getQName());
             }
         }
@@ -1671,7 +1666,7 @@ public final class TypeProviderImpl implements TypeProvider {
     }
 
     private static String union(final String className, final String defaultValue, final LeafSchemaNode node) {
-        StringBuilder sb = new StringBuilder();
+        final StringBuilder sb = new StringBuilder();
         sb.append("new ");
         sb.append(className);
         sb.append("(\"");