Yang parser refactoring.
[yangtools.git] / code-generator / binding-type-provider / src / main / java / org / opendaylight / yangtools / sal / binding / yang / types / TypeProviderImpl.java
index 858c2e0f09198de27a9ee3cc642541ebdc192c8c..9efd85ff6408182b37c59b44c3bf0e9a34ec4b82 100644 (file)
@@ -7,32 +7,41 @@
  */
 package org.opendaylight.yangtools.sal.binding.yang.types;
 
-import static org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil.*;
-import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.*;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
+import static org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil.moduleNamespaceToPackageName;
+import static org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil.packageNameForGeneratedType;
+import static org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil.parseToClassName;
+import static org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil.parseToValidParamName;
+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;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.net.URI;
+import java.util.*;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.lang3.StringEscapeUtils;
 import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil;
 import org.opendaylight.yangtools.binding.generator.util.TypeConstants;
 import org.opendaylight.yangtools.binding.generator.util.Types;
 import org.opendaylight.yangtools.binding.generator.util.generated.type.builder.EnumerationBuilderImpl;
+import org.opendaylight.yangtools.binding.generator.util.generated.type.builder.GeneratedPropertyBuilderImpl;
 import org.opendaylight.yangtools.binding.generator.util.generated.type.builder.GeneratedTOBuilderImpl;
 import org.opendaylight.yangtools.sal.binding.generator.spi.TypeProvider;
+import org.opendaylight.yangtools.sal.binding.model.api.AccessModifier;
+import org.opendaylight.yangtools.sal.binding.model.api.ConcreteType;
 import org.opendaylight.yangtools.sal.binding.model.api.Enumeration;
 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.yangtools.sal.binding.model.api.Restrictions;
 import org.opendaylight.yangtools.sal.binding.model.api.Type;
 import org.opendaylight.yangtools.sal.binding.model.api.type.builder.EnumBuilder;
 import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedPropertyBuilder;
 import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTOBuilder;
 import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.MethodSignatureBuilder;
+import org.opendaylight.yangtools.yang.binding.BindingMapping;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
@@ -43,19 +52,14 @@ 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.TypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.*;
 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition.Bit;
-import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
-import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
-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.UnionTypeDefinition;
-import org.opendaylight.yangtools.yang.model.util.ExtendedType;
-import org.opendaylight.yangtools.yang.model.util.StringType;
-import org.opendaylight.yangtools.yang.model.util.UnionType;
+import org.opendaylight.yangtools.yang.model.util.*;
 import org.opendaylight.yangtools.yang.parser.util.ModuleDependencySort;
 
 import com.google.common.base.Preconditions;
+import com.google.common.collect.Sets;
+import com.google.common.io.BaseEncoding;
 
 public final class TypeProviderImpl implements TypeProvider {
     /**
@@ -64,20 +68,19 @@ public final class TypeProviderImpl implements TypeProvider {
     private final SchemaContext schemaContext;
 
     /**
-     * The outter map maps module names to the map of the types for the module.
-     * The inner map maps the name of the concrete type to the JAVA
-     * <code>Type</code> (usually it is generated TO).
+     * Map<moduleName, Map<moduleDate, Map<typeName, type>>>
      */
-    private Map<String, Map<String, Type>> genTypeDefsContextMap;
+    private Map<String, Map<Date, Map<String, Type>>> genTypeDefsContextMap;
 
     /**
      * The map which maps schema paths to JAVA <code>Type</code>.
      */
     private final Map<SchemaPath, Type> referencedTypes;
+    private final Map<Module, Set<Type>> additionalTypes;
 
     /**
      * Creates new instance of class <code>TypeProviderImpl</code>.
-     * 
+     *
      * @param schemaContext
      *            contains the schema data red from YANG files
      * @throws IllegalArgumentException
@@ -89,12 +92,13 @@ public final class TypeProviderImpl implements TypeProvider {
         this.schemaContext = schemaContext;
         this.genTypeDefsContextMap = new HashMap<>();
         this.referencedTypes = new HashMap<>();
+        this.additionalTypes = new HashMap<>();
         resolveTypeDefsFromContext();
     }
 
     /**
      * Puts <code>refType</code> to map with key <code>refTypePath</code>
-     * 
+     *
      * @param refTypePath
      *            schema path used as the map key
      * @param refType
@@ -104,7 +108,7 @@ public final class TypeProviderImpl implements TypeProvider {
      *             <li>if <code>refTypePath</code> equal null</li>
      *             <li>if <code>refType</code> equal null</li>
      *             </ul>
-     * 
+     *
      */
     public void putReferencedType(final SchemaPath refTypePath, final Type refType) {
         Preconditions.checkArgument(refTypePath != null,
@@ -113,10 +117,14 @@ public final class TypeProviderImpl implements TypeProvider {
         referencedTypes.put(refTypePath, refType);
     }
 
+    public Map<Module, Set<Type>> getAdditionalTypes() {
+        return additionalTypes;
+    }
+
     /**
-     * 
+     *
      * Converts basic YANG type <code>type</code> to JAVA <code>Type</code>.
-     * 
+     *
      * @param type
      *            string with YANG name of type
      * @return JAVA <code>Type</code> for YANG type <code>type</code>
@@ -127,21 +135,27 @@ public final class TypeProviderImpl implements TypeProvider {
         return BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForYangType(type);
     }
 
+    @Override
+    public Type javaTypeForSchemaDefinitionType(final TypeDefinition<?> typeDefinition, final SchemaNode parentNode) {
+        return javaTypeForSchemaDefinitionType(typeDefinition, parentNode, null);
+    }
+
     /**
      * Converts schema definition type <code>typeDefinition</code> to JAVA
      * <code>Type</code>
-     * 
+     *
      * @param typeDefinition
      *            type definition which is converted to JAVA type
      * @throws IllegalArgumentException
      *             <ul>
      *             <li>if <code>typeDefinition</code> equal null</li>
-     *             <li>if Q name of <code>typeDefinition</code> equal null</li>
+     *             <li>if Qname of <code>typeDefinition</code> equal null</li>
      *             <li>if name of <code>typeDefinition</code> equal null</li>
      *             </ul>
      */
     @Override
-    public Type javaTypeForSchemaDefinitionType(final TypeDefinition<?> typeDefinition, final SchemaNode parentNode) {
+    public Type javaTypeForSchemaDefinitionType(final TypeDefinition<?> typeDefinition, final SchemaNode parentNode,
+            Restrictions r) {
         Type returnType = null;
         Preconditions.checkArgument(typeDefinition != null, "Type Definition cannot be NULL!");
         if (typeDefinition.getQName() == null) {
@@ -156,8 +170,8 @@ public final class TypeProviderImpl implements TypeProvider {
         } else {
             returnType = javaTypeForLeafrefOrIdentityRef(typeDefinition, parentNode);
             if (returnType == null) {
-                returnType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(typeDefinition,
-                        parentNode);
+                returnType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForYangType(typeDefinition.getQName()
+                        .getLocalName());
             }
         }
         // TODO: add throw exception when we will be able to resolve ALL yang
@@ -173,7 +187,7 @@ public final class TypeProviderImpl implements TypeProvider {
      * Returns JAVA <code>Type</code> for instances of the type
      * <code>LeafrefTypeDefinition</code> or
      * <code>IdentityrefTypeDefinition</code>.
-     * 
+     *
      * @param typeDefinition
      *            type definition which is converted to JAVA <code>Type</code>
      * @return JAVA <code>Type</code> instance for <code>typeDefinition</code>
@@ -193,7 +207,7 @@ public final class TypeProviderImpl implements TypeProvider {
     /**
      * Returns JAVA <code>Type</code> for instances of the type
      * <code>ExtendedType</code>.
-     * 
+     *
      * @param typeDefinition
      *            type definition which is converted to JAVA <code>Type</code>
      * @return JAVA <code>Type</code> instance for <code>typeDefinition</code>
@@ -209,14 +223,16 @@ public final class TypeProviderImpl implements TypeProvider {
                 returnType = provideTypeForEnum(enumTypeDef, typedefName, typeDefinition);
             } else {
                 final Module module = findParentModule(schemaContext, typeDefinition);
+                Restrictions r = BindingGeneratorUtil.getRestrictions(typeDefinition);
                 if (module != null) {
-                    final Map<String, Type> genTOs = genTypeDefsContextMap.get(module.getName());
+                    final Map<Date, Map<String, Type>> modulesByDate = genTypeDefsContextMap.get(module.getName());
+                    final Map<String, Type> genTOs = modulesByDate.get(module.getRevision());
                     if (genTOs != null) {
                         returnType = genTOs.get(typedefName);
                     }
                     if (returnType == null) {
                         returnType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(
-                                baseTypeDef, typeDefinition);
+                                baseTypeDef, typeDefinition, r);
                     }
                 }
             }
@@ -234,11 +250,11 @@ public final class TypeProviderImpl implements TypeProvider {
      * Seeks for identity reference <code>idref</code> the JAVA
      * <code>type</code>.<br />
      * <br />
-     * 
+     *
      * <i>Example:<br />
      * If identy which is referenced via <code>idref</code> has name <b>Idn</b>
      * then returning type is <b>{@code Class<? extends Idn>}</b></i>
-     * 
+     *
      * @param idref
      *            identityref type definition for which JAVA <code>Type</code>
      *            is sought
@@ -246,7 +262,7 @@ public final class TypeProviderImpl implements TypeProvider {
      *         <code>idref</code>
      */
     private Type provideTypeForIdentityref(IdentityrefTypeDefinition idref) {
-        QName baseIdQName = idref.getIdentity();
+        QName baseIdQName = idref.getIdentity().getQName();
         Module module = schemaContext.findModuleByNamespaceAndRevision(baseIdQName.getNamespace(),
                 baseIdQName.getRevision());
         IdentitySchemaNode identity = null;
@@ -268,7 +284,7 @@ public final class TypeProviderImpl implements TypeProvider {
 
     /**
      * Converts <code>typeDefinition</code> to concrete JAVA <code>Type</code>.
-     * 
+     *
      * @param typeDefinition
      *            type definition which should be converted to JAVA
      *            <code>Type</code>
@@ -300,7 +316,8 @@ public final class TypeProviderImpl implements TypeProvider {
                 final Module module = findParentModule(schemaContext, parentNode);
 
                 if (module != null) {
-                    final Map<String, Type> genTOs = genTypeDefsContextMap.get(module.getName());
+                    final Map<Date, Map<String, Type>> modulesByDate = genTypeDefsContextMap.get(module.getName());
+                    final Map<String, Type> genTOs = modulesByDate.get(module.getRevision());
                     if (genTOs != null) {
                         returnType = genTOs.get(typedefName);
                     }
@@ -313,7 +330,7 @@ public final class TypeProviderImpl implements TypeProvider {
     /**
      * Gets base type definition for <code>extendTypeDef</code>. The method is
      * recursivelly called until non <code>ExtendedType</code> type is found.
-     * 
+     *
      * @param extendTypeDef
      *            type definition for which is the base type definition sought
      * @return type definition which is base type for <code>extendTypeDef</code>
@@ -323,7 +340,9 @@ public final class TypeProviderImpl implements TypeProvider {
     private TypeDefinition<?> baseTypeDefForExtendedType(final TypeDefinition<?> extendTypeDef) {
         Preconditions.checkArgument(extendTypeDef != null, "Type Definiition reference cannot be NULL!");
         final TypeDefinition<?> baseTypeDef = extendTypeDef.getBaseType();
-        if (baseTypeDef instanceof ExtendedType) {
+        if (baseTypeDef == null) {
+            return extendTypeDef;
+        } else if (baseTypeDef instanceof ExtendedType) {
             return baseTypeDefForExtendedType(baseTypeDef);
         } else {
             return baseTypeDef;
@@ -333,10 +352,10 @@ public final class TypeProviderImpl implements TypeProvider {
 
     /**
      * Converts <code>leafrefType</code> to JAVA <code>Type</code>.
-     * 
+     *
      * The path of <code>leafrefType</code> is followed to find referenced node
      * and its <code>Type</code> is returned.
-     * 
+     *
      * @param leafrefType
      *            leafref type definition for which is the type sought
      * @return JAVA <code>Type</code> of data schema node which is referenced in
@@ -346,7 +365,7 @@ public final class TypeProviderImpl implements TypeProvider {
      *             <li>if <code>leafrefType</code> equal null</li>
      *             <li>if path statement of <code>leafrefType</code> equal null</li>
      *             </ul>
-     * 
+     *
      */
     public Type provideTypeForLeafref(final LeafrefTypeDefinition leafrefType, final SchemaNode parentNode) {
         Type returnType = null;
@@ -387,7 +406,7 @@ public final class TypeProviderImpl implements TypeProvider {
     /**
      * Checks if <code>dataNode</code> is <code>LeafSchemaNode</code> and if it
      * so then checks if it is of type <code>EnumTypeDefinition</code>.
-     * 
+     *
      * @param dataNode
      *            data schema node for which is checked if it is leaf and if it
      *            is of enum type
@@ -410,7 +429,7 @@ public final class TypeProviderImpl implements TypeProvider {
     /**
      * Checks if <code>dataNode</code> is <code>LeafListSchemaNode</code> and if
      * it so then checks if it is of type <code>EnumTypeDefinition</code>.
-     * 
+     *
      * @param dataNode
      *            data schema node for which is checked if it is leaflist and if
      *            it is of enum type
@@ -435,7 +454,7 @@ public final class TypeProviderImpl implements TypeProvider {
      * Converts <code>enumTypeDef</code> to
      * {@link org.opendaylight.yangtools.sal.binding.model.api.Enumeration
      * enumeration}.
-     * 
+     *
      * @param enumTypeDef
      *            enumeration type definition which is converted to enumeration
      * @param enumName
@@ -472,7 +491,7 @@ public final class TypeProviderImpl implements TypeProvider {
     /**
      * Adds enumeration to <code>typeBuilder</code>. The enumeration data are
      * taken from <code>enumTypeDef</code>.
-     * 
+     *
      * @param enumTypeDef
      *            enumeration type definition is source of enumeration data for
      *            <code>typeBuilder</code>
@@ -490,7 +509,7 @@ public final class TypeProviderImpl implements TypeProvider {
      *             <li>if name of <code>enumTypeDef</code> equal null</li>
      *             <li>if name of <code>typeBuilder</code> equal null</li>
      *             </ul>
-     * 
+     *
      */
     private Enumeration addInnerEnumerationToTypeBuilder(final EnumTypeDefinition enumTypeDef, final String enumName,
             final GeneratedTypeBuilderBase<?> typeBuilder) {
@@ -511,7 +530,7 @@ public final class TypeProviderImpl implements TypeProvider {
 
     /**
      * Converts <code>dataNode</code> to JAVA <code>Type</code>.
-     * 
+     *
      * @param dataNode
      *            contains information about YANG type
      * @return JAVA <code>Type</code> representation of <code>dataNode</code>
@@ -533,7 +552,7 @@ public final class TypeProviderImpl implements TypeProvider {
     /**
      * Passes through all modules and through all its type definitions and
      * convert it to generated types.
-     * 
+     *
      * The modules are firstly sorted by mutual dependencies. The modules are
      * sequentially passed. All type definitions of a module are at the
      * beginning sorted so that type definition with less amount of references
@@ -542,7 +561,7 @@ public final class TypeProviderImpl implements TypeProvider {
      * {@link TypeProviderImpl#genTypeDefsContextMap genTypeDefsContextMap}
      * which map current module name to the map which maps type names to
      * returned types (generated types).
-     * 
+     *
      */
     private void resolveTypeDefsFromContext() {
         final Set<Module> modules = schemaContext.getModules();
@@ -554,6 +573,16 @@ public final class TypeProviderImpl implements TypeProvider {
         }
         final List<Module> modulesSortedByDependency = ModuleDependencySort.sort(modulesArray);
 
+        for (final Module module : modulesSortedByDependency) {
+            Map<Date, Map<String, Type>> dateTypeMap = genTypeDefsContextMap.get(module.getName());
+            if (dateTypeMap == null) {
+                dateTypeMap = new HashMap<>();
+            }
+            final Map<String, Type> typeMap = new HashMap<>();
+            dateTypeMap.put(module.getRevision(), typeMap);
+            genTypeDefsContextMap.put(module.getName(), dateTypeMap);
+        }
+
         for (final Module module : modulesSortedByDependency) {
             if (module == null) {
                 continue;
@@ -561,22 +590,20 @@ public final class TypeProviderImpl implements TypeProvider {
             final String moduleName = module.getName();
             final String basePackageName = moduleNamespaceToPackageName(module);
 
-            final Set<TypeDefinition<?>> typeDefinitions = module.getTypeDefinitions();
+            final DataNodeIterator it = new DataNodeIterator(module);
+            final List<TypeDefinition<?>> typeDefinitions = it.allTypedefs();
             final List<TypeDefinition<?>> listTypeDefinitions = sortTypeDefinitionAccordingDepth(typeDefinitions);
 
-            final Map<String, Type> typeMap = new HashMap<>();
-            genTypeDefsContextMap.put(moduleName, typeMap);
-
             if ((listTypeDefinitions != null) && (basePackageName != null)) {
                 for (final TypeDefinition<?> typedef : listTypeDefinitions) {
-                    typedefToGeneratedType(basePackageName, moduleName, typedef);
+                    typedefToGeneratedType(basePackageName, module, typedef);
                 }
             }
         }
     }
 
     /**
-     * 
+     *
      * @param basePackageName
      *            string with name of package to which the module belongs
      * @param moduleName
@@ -590,8 +617,10 @@ public final class TypeProviderImpl implements TypeProvider {
      *         <code>modulName</code> or <code>typedef</code> or Q name of
      *         <code>typedef</code> equals <code>null</code>
      */
-    private Type typedefToGeneratedType(final String basePackageName, final String moduleName,
+    private Type typedefToGeneratedType(final String basePackageName, final Module module,
             final TypeDefinition<?> typedef) {
+        final String moduleName = module.getName();
+        final Date moduleRevision = module.getRevision();
         if ((basePackageName != null) && (moduleName != null) && (typedef != null) && (typedef.getQName() != null)) {
 
             final String typedefName = typedef.getQName().getLocalName();
@@ -601,29 +630,49 @@ public final class TypeProviderImpl implements TypeProvider {
                 Type returnType = null;
                 if (innerTypeDefinition instanceof ExtendedType) {
                     ExtendedType innerExtendedType = (ExtendedType) innerTypeDefinition;
-                    returnType = provideGeneratedTOFromExtendedType(innerExtendedType, basePackageName, typedefName);
+                    returnType = provideGeneratedTOFromExtendedType(typedef, innerExtendedType, basePackageName);
                 } else if (innerTypeDefinition instanceof UnionTypeDefinition) {
                     final GeneratedTOBuilder genTOBuilder = provideGeneratedTOBuilderForUnionTypeDef(basePackageName,
                             (UnionTypeDefinition) innerTypeDefinition, typedefName, typedef);
+                    genTOBuilder.setTypedef(true);
+                    genTOBuilder.setIsUnion(true);
+                    addUnitsToGenTO(genTOBuilder, typedef.getUnits());
                     returnType = genTOBuilder.toInstance();
+                    // union builder
+                    GeneratedTOBuilder unionBuilder = new GeneratedTOBuilderImpl(genTOBuilder.getPackageName(),
+                            genTOBuilder.getName() + "Builder");
+                    unionBuilder.setIsUnionBuilder(true);
+                    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);
+                    if (types == null) {
+                        types = Sets.<Type> newHashSet(unionBuilder.toInstance());
+                        additionalTypes.put(module, types);
+                    } else {
+                        types.add(unionBuilder.toInstance());
+                    }
                 } else if (innerTypeDefinition instanceof EnumTypeDefinition) {
                     final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) innerTypeDefinition;
+                    // TODO units for typedef enum
                     returnType = provideTypeForEnum(enumTypeDef, typedefName, typedef);
-
                 } else if (innerTypeDefinition instanceof BitsTypeDefinition) {
                     final BitsTypeDefinition bitsTypeDefinition = (BitsTypeDefinition) innerTypeDefinition;
                     final GeneratedTOBuilder genTOBuilder = provideGeneratedTOBuilderForBitsTypeDefinition(
                             basePackageName, bitsTypeDefinition, typedefName);
+                    genTOBuilder.setTypedef(true);
+                    addUnitsToGenTO(genTOBuilder, typedef.getUnits());
                     returnType = genTOBuilder.toInstance();
-
                 } else {
                     final Type javaType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(
                             innerTypeDefinition, typedef);
-
                     returnType = wrapJavaTypeIntoTO(basePackageName, typedef, javaType);
                 }
                 if (returnType != null) {
-                    final Map<String, Type> typeMap = genTypeDefsContextMap.get(moduleName);
+                    final Map<Date, Map<String, Type>> modulesByDate = genTypeDefsContextMap.get(moduleName);
+                    final Map<String, Type> typeMap = modulesByDate.get(moduleRevision);
                     if (typeMap != null) {
                         typeMap.put(typedefName, returnType);
                     }
@@ -636,7 +685,7 @@ public final class TypeProviderImpl implements TypeProvider {
 
     /**
      * Wraps base YANG type to generated TO.
-     * 
+     *
      * @param basePackageName
      *            string with name of package to which the module belongs
      * @param typedef
@@ -647,28 +696,29 @@ public final class TypeProviderImpl implements TypeProvider {
      */
     private GeneratedTransferObject wrapJavaTypeIntoTO(final String basePackageName, final TypeDefinition<?> typedef,
             final Type javaType) {
-        if (javaType != null) {
-            final String propertyName = "value";
-
-            final GeneratedTOBuilder genTOBuilder = typedefToTransferObject(basePackageName, typedef);
-            final GeneratedPropertyBuilder genPropBuilder = genTOBuilder.addProperty(propertyName);
-            genPropBuilder.setReturnType(javaType);
-            genTOBuilder.addEqualsIdentity(genPropBuilder);
-            genTOBuilder.addHashIdentity(genPropBuilder);
-            genTOBuilder.addToStringProperty(genPropBuilder);
-            if (javaType == BaseYangTypes.STRING_TYPE && typedef instanceof ExtendedType) {
-                final List<String> regExps = resolveRegExpressionsFromTypedef((ExtendedType) typedef);
-                addStringRegExAsConstant(genTOBuilder, regExps);
-            }
-            return genTOBuilder.toInstance();
+        Preconditions.checkNotNull(javaType, "javaType cannot be null");
+        final String propertyName = "value";
+
+        final GeneratedTOBuilder genTOBuilder = typedefToTransferObject(basePackageName, typedef);
+        genTOBuilder.setRestrictions(BindingGeneratorUtil.getRestrictions(typedef));
+        final GeneratedPropertyBuilder genPropBuilder = genTOBuilder.addProperty(propertyName);
+        genPropBuilder.setReturnType(javaType);
+        genTOBuilder.addEqualsIdentity(genPropBuilder);
+        genTOBuilder.addHashIdentity(genPropBuilder);
+        genTOBuilder.addToStringProperty(genPropBuilder);
+        if (javaType instanceof ConcreteType && "String".equals(javaType.getName()) && typedef instanceof ExtendedType) {
+            final List<String> regExps = resolveRegExpressionsFromTypedef((ExtendedType) typedef);
+            addStringRegExAsConstant(genTOBuilder, regExps);
         }
-        return null;
+        addUnitsToGenTO(genTOBuilder, typedef.getUnits());
+        genTOBuilder.setTypedef(true);
+        return genTOBuilder.toInstance();
     }
 
     /**
      * Converts output list of generated TO builders to one TO builder (first
      * from list) which contains the remaining builders as its enclosing TO.
-     * 
+     *
      * @param basePackageName
      *            string with name of package to which the module belongs
      * @param typedef
@@ -685,12 +735,18 @@ public final class TypeProviderImpl implements TypeProvider {
                 typedef, typeDefName, parentNode);
         GeneratedTOBuilder resultTOBuilder = null;
         if (!genTOBuilders.isEmpty()) {
-            resultTOBuilder = genTOBuilders.get(0);
-            genTOBuilders.remove(0);
+            resultTOBuilder = genTOBuilders.remove(0);
             for (GeneratedTOBuilder genTOBuilder : genTOBuilders) {
                 resultTOBuilder.addEnclosingTransferObject(genTOBuilder);
             }
         }
+
+        final GeneratedPropertyBuilder genPropBuilder = resultTOBuilder.addProperty("value");
+        genPropBuilder.setReturnType(Types.primitiveType("char[]", null));
+        resultTOBuilder.addEqualsIdentity(genPropBuilder);
+        resultTOBuilder.addHashIdentity(genPropBuilder);
+        resultTOBuilder.addToStringProperty(genPropBuilder);
+
         return resultTOBuilder;
     }
 
@@ -698,7 +754,7 @@ public final class TypeProviderImpl implements TypeProvider {
      * Converts <code>typedef</code> to generated TO with
      * <code>typeDefName</code>. Every union type from <code>typedef</code> is
      * added to generated TO builder as property.
-     * 
+     *
      * @param basePackageName
      *            string with name of package to which the module belongs
      * @param typedef
@@ -707,73 +763,71 @@ public final class TypeProviderImpl implements TypeProvider {
      * @param typeDefName
      *            string with name for generated TO
      * @return generated TO builder which represents <code>typedef</code>
-     * @throws IllegalArgumentException
+     * @throws NullPointerException
      *             <ul>
-     *             <li>if <code>basePackageName</code> equals null</li>
-     *             <li>if <code>typedef</code> equals null</li>
-     *             <li>if Q name of <code>typedef</code> equals null</li>
+     *             <li>if <code>basePackageName</code> is null</li>
+     *             <li>if <code>typedef</code> is null</li>
+     *             <li>if Qname of <code>typedef</code> is null</li>
      *             </ul>
      */
     public List<GeneratedTOBuilder> provideGeneratedTOBuildersForUnionTypeDef(final String basePackageName,
             final UnionTypeDefinition typedef, final String typeDefName, final SchemaNode parentNode) {
-        Preconditions.checkArgument(basePackageName != null, "Base Package Name cannot be NULL!");
-        Preconditions.checkArgument(typedef != null, "Type Definition cannot be NULL!");
-        Preconditions.checkArgument(typedef.getQName() != null,
-                "Type Definition cannot have non specified QName (QName cannot be NULL!)");
+        Preconditions.checkNotNull(basePackageName, "Base Package Name cannot be NULL!");
+        Preconditions.checkNotNull(typedef, "Type Definition cannot be NULL!");
+        Preconditions.checkNotNull(typedef.getQName(), "Type definition QName cannot be NULL!");
 
         final List<GeneratedTOBuilder> generatedTOBuilders = new ArrayList<>();
+        final List<TypeDefinition<?>> unionTypes = typedef.getTypes();
 
-        if (typedef != null) {
-            final List<TypeDefinition<?>> unionTypes = typedef.getTypes();
+        final GeneratedTOBuilder unionGenTOBuilder;
+        if (typeDefName != null && !typeDefName.isEmpty()) {
+            final String typeName = parseToClassName(typeDefName);
+            unionGenTOBuilder = new GeneratedTOBuilderImpl(basePackageName, typeName);
+        } else {
+            unionGenTOBuilder = typedefToTransferObject(basePackageName, typedef);
+        }
 
-            final GeneratedTOBuilder unionGenTOBuilder;
-            if (typeDefName != null && !typeDefName.isEmpty()) {
-                final String typeName = parseToClassName(typeDefName);
-                unionGenTOBuilder = new GeneratedTOBuilderImpl(basePackageName, typeName);
+        generatedTOBuilders.add(unionGenTOBuilder);
+        unionGenTOBuilder.setIsUnion(true);
+        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,
+                        parentNode);
+            } else if (unionType instanceof EnumTypeDefinition) {
+                final Enumeration enumeration = addInnerEnumerationToTypeBuilder((EnumTypeDefinition) unionType,
+                        unionTypeName, unionGenTOBuilder);
+                updateUnionTypeAsProperty(unionGenTOBuilder, enumeration, unionTypeName);
             } else {
-                unionGenTOBuilder = typedefToTransferObject(basePackageName, typedef);
-            }
-            generatedTOBuilders.add(unionGenTOBuilder);
-            unionGenTOBuilder.setIsUnion(true);
-            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, unionTypeName,
-                            regularExpressions, 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);
-                    updateUnionTypeAsProperty(unionGenTOBuilder, javaType, unionTypeName);
-                }
-            }
-            if (!regularExpressions.isEmpty()) {
-                addStringRegExAsConstant(unionGenTOBuilder, regularExpressions);
+                final Type javaType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(unionType,
+                        parentNode);
+                updateUnionTypeAsProperty(unionGenTOBuilder, javaType, unionTypeName);
             }
-
-            storeGenTO(typedef, unionGenTOBuilder, parentNode);
         }
+        if (!regularExpressions.isEmpty()) {
+            addStringRegExAsConstant(unionGenTOBuilder, regularExpressions);
+        }
+
+        storeGenTO(typedef, unionGenTOBuilder, parentNode);
+
         return generatedTOBuilders;
     }
 
     /**
      * Wraps code which handle case when union subtype is also of the type
      * <code>UnionType</code>.
-     * 
+     *
      * In this case the new generated TO is created for union subtype (recursive
      * call of method
      * {@link #provideGeneratedTOBuildersForUnionTypeDef(String, TypeDefinition, String)
      * provideGeneratedTOBuilderForUnionTypeDef} and in parent TO builder
      * <code>parentUnionGenTOBuilder</code> is created property which type is
      * equal to new generated TO.
-     * 
+     *
      * @param parentUnionGenTOBuilder
      *            generated TO builder to which is the property with the child
      *            union subtype added
@@ -804,11 +858,11 @@ public final class TypeProviderImpl implements TypeProvider {
     /**
      * Wraps code which handle case when union subtype is of the type
      * <code>ExtendedType</code>.
-     * 
+     *
      * If TO for this type already exists it is used for the creation of the
      * property in <code>parentUnionGenTOBuilder</code>. In other case the base
      * type is used for the property creation.
-     * 
+     *
      * @param parentUnionGenTOBuilder
      *            generated TO builder in which new property is created
      * @param unionSubtype
@@ -820,9 +874,10 @@ public final class TypeProviderImpl implements TypeProvider {
      *            list of strings with the regular expressions
      */
     private void resolveExtendedSubtypeAsUnion(final GeneratedTOBuilder parentUnionGenTOBuilder,
-            final ExtendedType unionSubtype, final String unionTypeName, final List<String> regularExpressions,
+            final ExtendedType unionSubtype, final List<String> regularExpressions,
             final SchemaNode parentNode) {
-        final Type genTO = findGenTO(unionTypeName, parentNode);
+        final String unionTypeName = unionSubtype.getQName().getLocalName();
+        final Type genTO = findGenTO(unionTypeName, unionSubtype);
         if (genTO != null) {
             updateUnionTypeAsProperty(parentUnionGenTOBuilder, genTO, genTO.getName());
         } else {
@@ -843,7 +898,7 @@ public final class TypeProviderImpl implements TypeProvider {
     /**
      * Searches for generated TO for <code>searchedTypeDef</code> type
      * definition in {@link #genTypeDefsContextMap genTypeDefsContextMap}
-     * 
+     *
      * @param searchedTypeName
      *            string with name of <code>searchedTypeDef</code>
      * @return generated TO for <code>searchedTypeDef</code> or
@@ -852,7 +907,8 @@ public final class TypeProviderImpl implements TypeProvider {
     private Type findGenTO(final String searchedTypeName, final SchemaNode parentNode) {
         final Module typeModule = findParentModule(schemaContext, parentNode);
         if (typeModule != null && typeModule.getName() != null) {
-            final Map<String, Type> genTOs = genTypeDefsContextMap.get(typeModule.getName());
+            final Map<Date, Map<String, Type>> modulesByDate = genTypeDefsContextMap.get(typeModule.getName());
+            final Map<String, Type> genTOs = modulesByDate.get(typeModule.getRevision());
             if (genTOs != null) {
                 return genTOs.get(searchedTypeName);
             }
@@ -864,7 +920,7 @@ public final class TypeProviderImpl implements TypeProvider {
      * Stores generated TO created from <code>genTOBuilder</code> for
      * <code>newTypeDef</code> to {@link #genTypeDefsContextMap
      * genTypeDefsContextMap} if the module for <code>newTypeDef</code> exists
-     * 
+     *
      * @param newTypeDef
      *            type definition for which is <code>genTOBuilder</code> created
      * @param genTOBuilder
@@ -873,10 +929,11 @@ public final class TypeProviderImpl implements TypeProvider {
      */
     private void storeGenTO(TypeDefinition<?> newTypeDef, GeneratedTOBuilder genTOBuilder, SchemaNode parentNode) {
         if (!(newTypeDef instanceof UnionType)) {
-            Map<String, Type> genTOsMap = null;
+
             final Module parentModule = findParentModule(schemaContext, parentNode);
             if (parentModule != null && parentModule.getName() != null) {
-                genTOsMap = genTypeDefsContextMap.get(parentModule.getName());
+                Map<Date, Map<String, Type>> modulesByDate = genTypeDefsContextMap.get(parentModule.getName());
+                Map<String, Type> genTOsMap = modulesByDate.get(parentModule.getRevision());
                 genTOsMap.put(newTypeDef.getQName().getLocalName(), genTOBuilder.toInstance());
             }
         }
@@ -885,7 +942,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>.
-     * 
+     *
      * @param unionGenTransObject
      *            generated TO to which should be property added
      * @param type
@@ -910,7 +967,7 @@ public final class TypeProviderImpl implements TypeProvider {
 
     /**
      * Converts <code>typedef</code> to the generated TO builder.
-     * 
+     *
      * @param basePackageName
      *            string with name of package to which the module belongs
      * @param typedef
@@ -935,10 +992,10 @@ public final class TypeProviderImpl implements TypeProvider {
     /**
      * Converts <code>typeDef</code> which should be of the type
      * <code>BitsTypeDefinition</code> to <code>GeneratedTOBuilder</code>.
-     * 
+     *
      * All the bits of the typeDef are added to returning generated TO as
      * properties.
-     * 
+     *
      * @param basePackageName
      *            string with name of package to which the module belongs
      * @param typeDef
@@ -985,13 +1042,13 @@ public final class TypeProviderImpl implements TypeProvider {
     /**
      * Converts the pattern constraints from <code>typedef</code> to the list of
      * the strings which represents these constraints.
-     * 
+     *
      * @param typedef
      *            extended type in which are the pattern constraints sought
      * @return list of strings which represents the constraint patterns
      * @throws IllegalArgumentException
      *             if <code>typedef</code> equals null
-     * 
+     *
      */
     private List<String> resolveRegExpressionsFromTypedef(ExtendedType typedef) {
         final List<String> regExps = new ArrayList<String>();
@@ -1013,10 +1070,10 @@ public final class TypeProviderImpl implements TypeProvider {
     }
 
     /**
-     * 
+     *
      * Adds to the <code>genTOBuilder</code> the constant which contains regular
      * expressions from the <code>regularExpressions</code>
-     * 
+     *
      * @param genTOBuilder
      *            generated TO builder to which are
      *            <code>regular expressions</code> added
@@ -1046,11 +1103,11 @@ public final class TypeProviderImpl implements TypeProvider {
      * <code>innerExtendedType</code>, about the package name
      * <code>typedefName</code> and about the generated TO name
      * <code>typedefName</code>.
-     * 
+     *
      * It is supposed that <code>innerExtendedType</code> is already present in
      * {@link TypeProviderImpl#genTypeDefsContextMap genTypeDefsContextMap} to
      * be possible set it as extended type for the returning generated TO.
-     * 
+     *
      * @param innerExtendedType
      *            extended type which is part of some other extended type
      * @param basePackageName
@@ -1066,21 +1123,29 @@ public final class TypeProviderImpl implements TypeProvider {
      *             <li>if <code>typedefName</code> equals null</li>
      *             </ul>
      */
-    private GeneratedTransferObject provideGeneratedTOFromExtendedType(final ExtendedType innerExtendedType,
-            final String basePackageName, final String typedefName) {
-
+    private GeneratedTransferObject provideGeneratedTOFromExtendedType(final TypeDefinition<?> typedef,
+            final ExtendedType innerExtendedType, final String basePackageName) {
         Preconditions.checkArgument(innerExtendedType != null, "Extended type cannot be NULL!");
         Preconditions.checkArgument(basePackageName != null, "String with base package name cannot be NULL!");
-        Preconditions.checkArgument(typedefName != null, "String with type definition name cannot be NULL!");
 
+        final String typedefName = typedef.getQName().getLocalName();
         final String classTypedefName = parseToClassName(typedefName);
         final String innerTypeDef = innerExtendedType.getQName().getLocalName();
         final GeneratedTOBuilder genTOBuilder = new GeneratedTOBuilderImpl(basePackageName, classTypedefName);
+        genTOBuilder.setTypedef(true);
+        Restrictions r = BindingGeneratorUtil.getRestrictions(typedef);
+        genTOBuilder.setRestrictions(r);
+
+        if (baseTypeDefForExtendedType(innerExtendedType) instanceof UnionTypeDefinition) {
+            genTOBuilder.setIsUnion(true);
+        }
 
+        Map<Date, Map<String, Type>> modulesByDate = null;
         Map<String, Type> typeMap = null;
         final Module parentModule = findParentModule(schemaContext, innerExtendedType);
         if (parentModule != null) {
-            typeMap = genTypeDefsContextMap.get(parentModule.getName());
+            modulesByDate = genTypeDefsContextMap.get(parentModule.getName());
+            typeMap = modulesByDate.get(parentModule.getRevision());
         }
 
         if (typeMap != null) {
@@ -1089,6 +1154,7 @@ public final class TypeProviderImpl implements TypeProvider {
                 genTOBuilder.setExtendsType((GeneratedTransferObject) type);
             }
         }
+        addUnitsToGenTO(genTOBuilder, typedef.getUnits());
 
         return genTOBuilder.toInstance();
     }
@@ -1100,7 +1166,7 @@ public final class TypeProviderImpl implements TypeProvider {
      * equal depth. In next step are lists from this map concatenated to one
      * list in ascending order according to their depth. All type definitions
      * are in the list behind all type definitions on which depends.
-     * 
+     *
      * @param unsortedTypeDefinitions
      *            list of type definitions which should be sorted by depth
      * @return list of type definitions sorted according their each other
@@ -1108,7 +1174,7 @@ public final class TypeProviderImpl implements TypeProvider {
      *         definitions are in list behind them).
      */
     private List<TypeDefinition<?>> sortTypeDefinitionAccordingDepth(
-            final Set<TypeDefinition<?>> unsortedTypeDefinitions) {
+            final Collection<TypeDefinition<?>> unsortedTypeDefinitions) {
         List<TypeDefinition<?>> sortedTypeDefinition = new ArrayList<>();
 
         Map<Integer, List<TypeDefinition<?>>> typeDefinitionsDepths = new TreeMap<>();
@@ -1133,7 +1199,7 @@ public final class TypeProviderImpl implements TypeProvider {
     /**
      * Returns how many immersion is necessary to get from the type definition
      * to the base type.
-     * 
+     *
      * @param typeDefinition
      *            type definition for which is depth sought.
      * @return number of immersions which are necessary to get from the type
@@ -1153,7 +1219,7 @@ public final class TypeProviderImpl implements TypeProvider {
             int maxChildDepth = 0;
             int childDepth = 1;
             for (TypeDefinition<?> childTypeDefinition : childTypeDefinitions) {
-                childDepth = childDepth + getTypeDefinitionDepth(childTypeDefinition.getBaseType());
+                childDepth = childDepth + getTypeDefinitionDepth(childTypeDefinition);
                 if (childDepth > maxChildDepth) {
                     maxChildDepth = childDepth;
                 }
@@ -1167,7 +1233,7 @@ public final class TypeProviderImpl implements TypeProvider {
      * Returns string which contains the same value as <code>name</code> but
      * integer suffix is incremented by one. If <code>name</code> contains no
      * number suffix then number 1 is added.
-     * 
+     *
      * @param name
      *            string with name of augmented node
      * @return string with the number suffix incremented by one (or 1 is added)
@@ -1183,4 +1249,273 @@ public final class TypeProviderImpl implements TypeProvider {
         }
     }
 
+    public void addUnitsToGenTO(GeneratedTOBuilder to, String units) {
+        if (units != null && !units.isEmpty()) {
+            to.addConstant(Types.STRING, "_UNITS", "\"" + units + "\"");
+            GeneratedPropertyBuilder prop = new GeneratedPropertyBuilderImpl("UNITS");
+            prop.setReturnType(Types.STRING);
+            to.addToStringProperty(prop);
+        }
+    }
+
+    @Override
+    public String getTypeDefaultConstruction(LeafSchemaNode node) {
+        return getTypeDefaultConstruction(node, node.getDefault());
+    }
+
+    public String getTypeDefaultConstruction(LeafSchemaNode node, String defaultValue) {
+        TypeDefinition<?> type = node.getType();
+        QName typeQName = type.getQName();
+        TypeDefinition<?> base = baseTypeDefForExtendedType(type);
+        Preconditions.checkNotNull(type, "Cannot provide default construction for null type of " + node);
+        Preconditions.checkNotNull(defaultValue, "Cannot provide default construction for null default statement of "
+                + node);
+
+        StringBuilder sb = new StringBuilder();
+        String result = null;
+        if (base instanceof BinaryTypeDefinition) {
+            result = binaryToDef(defaultValue);
+        } else if (base instanceof BitsTypeDefinition) {
+            String parentName;
+            String className;
+            SchemaPath nodePath = node.getPath();
+            Module parent = getParentModule(node);
+            if (nodePath.getPath().size() == 1) {
+                parentName = BindingMapping.getClassName((parent).getName()) + "Data";
+                String basePackageName = BindingGeneratorUtil.moduleNamespaceToPackageName(parent);
+                className = basePackageName + "." + parentName + "." + BindingMapping.getClassName(node.getQName());
+            } else {
+                String basePackageName = BindingGeneratorUtil.moduleNamespaceToPackageName(parent);
+                String packageName = packageNameForGeneratedType(basePackageName, type.getPath());
+                parentName = BindingMapping.getClassName(((SchemaNode) parent).getQName());
+                className = packageName + "." + parentName + "." + BindingMapping.getClassName(node.getQName());
+            }
+            result = bitsToDef((BitsTypeDefinition) base, className, defaultValue, type instanceof ExtendedType);
+        } else if (base instanceof BooleanTypeDefinition) {
+            result = typeToDef(Boolean.class, defaultValue);
+        } else if (base instanceof DecimalTypeDefinition) {
+            result = typeToDef(BigDecimal.class, defaultValue);
+        } 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));
+            defValArray[0] = first;
+            String newDefVal = new String(defValArray);
+            String className;
+            if (type instanceof ExtendedType) {
+                Module m = getParentModule(type);
+                String basePackageName = BindingGeneratorUtil.moduleNamespaceToPackageName(m);
+                String packageName = packageNameForGeneratedType(basePackageName, type.getPath());
+                className = packageName + "." + BindingMapping.getClassName(typeQName);
+            } else {
+                Module parentModule = getParentModule(node);
+                String basePackageName = BindingGeneratorUtil.moduleNamespaceToPackageName(parentModule);
+                String packageName = packageNameForGeneratedType(basePackageName, node.getPath());
+                className = packageName + "." + BindingMapping.getClassName(node.getQName());
+            }
+            result = className + "." + newDefVal;
+        } else if (base instanceof IdentityrefTypeDefinition) {
+            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) {
+            result = typeToDef(Byte.class, defaultValue);
+        } else if (base instanceof Int16) {
+            result = typeToDef(Short.class, defaultValue);
+        } else if (base instanceof Int32) {
+            result = typeToDef(Integer.class, defaultValue);
+        } else if (base instanceof Int64) {
+            result = typeToDef(Long.class, defaultValue);
+        } else if (base instanceof LeafrefTypeDefinition) {
+            result = leafrefToDef(node, (LeafrefTypeDefinition) base);
+        } else if (base instanceof StringTypeDefinition) {
+            result = "\"" + defaultValue + "\"";
+        } else if (base instanceof Uint8) {
+            result = typeToDef(Short.class, defaultValue);
+        } else if (base instanceof Uint16) {
+            result = typeToDef(Integer.class, defaultValue);
+        } else if (base instanceof Uint32) {
+            result = typeToDef(Long.class, defaultValue);
+        } else if (base instanceof Uint64) {
+            result = typeToDef(BigInteger.class, defaultValue);
+        } else if (base instanceof UnionTypeDefinition) {
+            result = unionToDef(node);
+        } else {
+            result = "";
+        }
+        sb.append(result);
+
+        if (type instanceof ExtendedType && !(base instanceof LeafrefTypeDefinition)
+                && !(base instanceof EnumerationType) && !(base instanceof UnionTypeDefinition)) {
+            Module m = getParentModule(type);
+            String basePackageName = BindingGeneratorUtil.moduleNamespaceToPackageName(m);
+            String packageName = packageNameForGeneratedType(basePackageName, type.getPath());
+            String className = packageName + "." + BindingMapping.getClassName(typeQName);
+            sb.insert(0, "new " + className + "(");
+            sb.insert(sb.length(), ")");
+        }
+
+        return sb.toString();
+    }
+
+    private String typeToDef(Class<?> clazz, String defaultValue) {
+        return "new " + clazz.getName() + "(\"" + defaultValue + "\")";
+    }
+
+    private String binaryToDef(String defaultValue) {
+        StringBuilder sb = new StringBuilder();
+        BaseEncoding en = BaseEncoding.base64();
+        byte[] encoded = en.decode(defaultValue);
+        sb.append("new byte[] {");
+        for (int i = 0; i < encoded.length; i++) {
+            sb.append(encoded[i]);
+            if (i != encoded.length - 1) {
+                sb.append(", ");
+            }
+        }
+        sb.append("}");
+        return sb.toString();
+    }
+
+    private String bitsToDef(BitsTypeDefinition type, String className, String defaultValue, boolean isExt) {
+        List<Bit> bits = new ArrayList<>(type.getBits());
+        Collections.sort(bits, new Comparator<Bit>() {
+            @Override
+            public int compare(Bit o1, Bit o2) {
+                return o1.getName().compareTo(o2.getName());
+            }
+        });
+        StringBuilder sb = new StringBuilder();
+        sb.append(isExt ? "" : "new " + className + "(");
+        for (int i = 0; i < bits.size(); i++) {
+            if (bits.get(i).getName().equals(defaultValue)) {
+                sb.append(true);
+            } else {
+                sb.append(false);
+            }
+            if (i != bits.size() - 1) {
+                sb.append(", ");
+            }
+        }
+        sb.append(isExt ? "" : ")");
+        return sb.toString();
+    }
+
+    private Module getParentModule(SchemaNode node) {
+        QName qname = node.getPath().getPath().get(0);
+        URI namespace = qname.getNamespace();
+        Date revision = qname.getRevision();
+        return schemaContext.findModuleByNamespaceAndRevision(namespace, revision);
+    }
+
+    private String leafrefToDef(LeafSchemaNode parentNode, LeafrefTypeDefinition leafrefType) {
+        Preconditions.checkArgument(leafrefType != null, "Leafref Type Definition reference cannot be NULL!");
+        Preconditions.checkArgument(leafrefType.getPathStatement() != null,
+                "The Path Statement for Leafref Type Definition cannot be NULL!");
+
+        final RevisionAwareXPath xpath = leafrefType.getPathStatement();
+        final String strXPath = xpath.toString();
+
+        if (strXPath != null) {
+            if (strXPath.contains("[")) {
+                return "new java.lang.Object()";
+            } else {
+                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);
+                    }
+                    String result = getTypeDefaultConstruction((LeafSchemaNode) dataNode, parentNode.getDefault());
+                    return result;
+                }
+            }
+        }
+
+        return null;
+    }
+
+    private String unionToDef(LeafSchemaNode node) {
+        String parentName;
+        String className;
+
+        if (node.getType() instanceof ExtendedType) {
+            ExtendedType type = (ExtendedType) node.getType();
+            QName typeQName = type.getQName();
+            Module module = null;
+            Set<Module> modules = schemaContext.findModuleByNamespace(typeQName.getNamespace());
+            if (modules.size() > 1) {
+                for (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(Module o1, Module o2) {
+                            return o1.getRevision().compareTo(o2.getRevision());
+                        }
+                    });
+                    module = modulesList.get(0);
+                }
+            } else {
+                module = modules.iterator().next();
+            }
+
+            String basePackageName = BindingGeneratorUtil.moduleNamespaceToPackageName(module);
+            className = basePackageName + "." + BindingMapping.getClassName(typeQName);
+        } else {
+            SchemaPath nodePath = node.getPath();
+            if (nodePath.getPath().size() == 1) {
+                QName first = nodePath.getPath().get(0);
+                URI namespace = first.getNamespace();
+                Date revision = first.getRevision();
+                Module parent = schemaContext.findModuleByNamespaceAndRevision(namespace, revision);
+                parentName = BindingMapping.getClassName((parent).getName()) + "Data";
+                String basePackageName = BindingGeneratorUtil.moduleNamespaceToPackageName(parent);
+                className = basePackageName + "." + parentName + "." + BindingMapping.getClassName(node.getQName());
+            } else {
+                QName first = node.getPath().getPath().get(0);
+                URI namespace = first.getNamespace();
+                Date revision = first.getRevision();
+                Module parentModule = schemaContext.findModuleByNamespaceAndRevision(namespace, revision);
+                String basePackageName = BindingGeneratorUtil.moduleNamespaceToPackageName(parentModule);
+                String packageName = packageNameForGeneratedType(basePackageName, node.getType().getPath());
+                className = packageName + "." + BindingMapping.getClassName(node.getQName());
+            }
+        }
+        return union(className, node.getDefault(), node);
+    }
+
+    private String union(String className, String defaultValue, LeafSchemaNode node) {
+        StringBuilder sb = new StringBuilder();
+        sb.append("new " + className + "(");
+        sb.append("\"");
+        sb.append(defaultValue);
+        sb.append("\"");
+        sb.append(".toCharArray()");
+        sb.append(")");
+        return sb.toString();
+    }
+
+    @Override
+    public String getConstructorPropertyName(SchemaNode node) {
+        if (node instanceof TypeDefinition<?>) {
+            return "value";
+        } else {
+            return "";
+        }
+    }
+
+    @Override
+    public String getParamNameFromType(TypeDefinition<?> type) {
+        return BindingGeneratorUtil.parseToValidParamName(type.getQName().getLocalName());
+    }
+
 }