Implemented range validation (Bug 178).
[mdsal.git] / code-generator / binding-type-provider / src / main / java / org / opendaylight / yangtools / sal / binding / yang / types / TypeProviderImpl.java
index 712d079c32fd60b74f1375533a606e05085f7b9d..568428738bfb78247b33bdbaa109e26d42556008 100644 (file)
@@ -10,8 +10,13 @@ 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.math.BigDecimal;
+import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -25,6 +30,7 @@ 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.ConcreteType;
@@ -37,6 +43,8 @@ import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedPr
 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.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
@@ -46,20 +54,36 @@ 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.YangNode;
+import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition.Bit;
+import org.opendaylight.yangtools.yang.model.api.type.BooleanTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition;
 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.InstanceIdentifierTypeDefinition;
 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.DataNodeIterator;
 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.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.parser.util.ModuleDependencySort;
 
 import com.google.common.base.Preconditions;
+import com.google.common.io.BaseEncoding;
 
 public final class TypeProviderImpl implements TypeProvider {
     /**
@@ -68,11 +92,9 @@ 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>.
@@ -145,12 +167,13 @@ public final class TypeProviderImpl implements TypeProvider {
      * @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, Restrictions r) {
+    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) {
@@ -165,8 +188,8 @@ public final class TypeProviderImpl implements TypeProvider {
         } else {
             returnType = javaTypeForLeafrefOrIdentityRef(typeDefinition, parentNode);
             if (returnType == null) {
-                returnType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(typeDefinition,
-                        parentNode, r);
+                returnType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForYangType(typeDefinition.getQName()
+                        .getLocalName());
             }
         }
         // TODO: add throw exception when we will be able to resolve ALL yang
@@ -220,7 +243,8 @@ public final class TypeProviderImpl implements TypeProvider {
                 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);
                     }
@@ -310,7 +334,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);
                     }
@@ -333,7 +358,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;
@@ -564,6 +591,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;
@@ -575,12 +612,9 @@ public final class TypeProviderImpl implements TypeProvider {
             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, moduleName, module.getRevision(), typedef);
                 }
             }
         }
@@ -602,7 +636,7 @@ public final class TypeProviderImpl implements TypeProvider {
      *         <code>typedef</code> equals <code>null</code>
      */
     private Type typedefToGeneratedType(final String basePackageName, final String moduleName,
-            final TypeDefinition<?> typedef) {
+            final Date moduleRevision, final TypeDefinition<?> typedef) {
         if ((basePackageName != null) && (moduleName != null) && (typedef != null) && (typedef.getQName() != null)) {
 
             final String typedefName = typedef.getQName().getLocalName();
@@ -616,16 +650,20 @@ public final class TypeProviderImpl implements TypeProvider {
                 } 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();
                 } 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(
@@ -633,7 +671,9 @@ public final class TypeProviderImpl implements TypeProvider {
                     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);
                     }
@@ -657,23 +697,23 @@ 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);
-            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 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();
     }
 
     /**
@@ -696,8 +736,7 @@ 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);
             }
@@ -863,7 +902,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);
             }
@@ -884,10 +924,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());
             }
         }
@@ -1077,8 +1118,8 @@ public final class TypeProviderImpl implements TypeProvider {
      *             <li>if <code>typedefName</code> equals null</li>
      *             </ul>
      */
-    private GeneratedTransferObject provideGeneratedTOFromExtendedType(final TypeDefinition<?> typedef, final ExtendedType innerExtendedType,
-            final String basePackageName) {
+    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!");
 
@@ -1086,6 +1127,7 @@ public final class TypeProviderImpl implements TypeProvider {
         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);
 
@@ -1093,10 +1135,12 @@ public final class TypeProviderImpl implements TypeProvider {
             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) {
@@ -1105,6 +1149,7 @@ public final class TypeProviderImpl implements TypeProvider {
                 genTOBuilder.setExtendsType((GeneratedTransferObject) type);
             }
         }
+        addUnitsToGenTO(genTOBuilder, typedef.getUnits());
 
         return genTOBuilder.toInstance();
     }
@@ -1199,4 +1244,222 @@ public final class TypeProviderImpl implements TypeProvider {
         }
     }
 
+    private 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;
+            YangNode parent = node.getParent();
+            if (parent instanceof Module) {
+                parentName = parseToClassName(((Module) parent).getName()) + "Data";
+                String basePackageName = BindingGeneratorUtil.moduleNamespaceToPackageName((Module) parent);
+                className = basePackageName + "." + parentName + "." + parseToClassName(node.getQName().getLocalName());
+            } else {
+                Module parentModule = getParentModule(node);
+                String basePackageName = BindingGeneratorUtil.moduleNamespaceToPackageName(parentModule);
+                String packageName = packageNameForGeneratedType(basePackageName, type.getPath());
+                parentName = parseToClassName(((SchemaNode) parent).getQName().getLocalName());
+                className = packageName + "." + parentName + "." + parseToClassName(node.getQName().getLocalName());
+            }
+            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) {
+                QName qname = type.getPath().getPath().get(0);
+                Module m = schemaContext.findModuleByNamespaceAndRevision(qname.getNamespace(), qname.getRevision());
+                String basePackageName = BindingGeneratorUtil.moduleNamespaceToPackageName(m);
+                String packageName = packageNameForGeneratedType(basePackageName, type.getPath());
+                className = packageName + "." + parseToClassName(typeQName.getLocalName());
+            } else {
+                Module parentModule = getParentModule(node);
+                String basePackageName = BindingGeneratorUtil.moduleNamespaceToPackageName(parentModule);
+                String packageName = packageNameForGeneratedType(basePackageName, node.getPath());
+                className = packageName + "." + parseToClassName(node.getQName().getLocalName());
+            }
+            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) {
+            throw new UnsupportedOperationException("Cannot get default construction for union type");
+        } else {
+            result = "";
+        }
+        sb.append(result);
+
+        if (type instanceof ExtendedType && !(base instanceof LeafrefTypeDefinition)) {
+            QName qname = type.getPath().getPath().get(0);
+            Module m = schemaContext.findModuleByNamespaceAndRevision(qname.getNamespace(), qname.getRevision());
+            String basePackageName = BindingGeneratorUtil.moduleNamespaceToPackageName(m);
+            String packageName = packageNameForGeneratedType(basePackageName, type.getPath());
+            String className = packageName + "." + parseToClassName(typeQName.getLocalName());
+            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(YangNode node) {
+        if (node instanceof Module) {
+            return (Module) node;
+        }
+
+        YangNode parent = null;
+        if (node instanceof DataSchemaNode) {
+            parent = ((DataSchemaNode) node).getParent();
+        } else if (node instanceof DataNodeContainer) {
+            parent = ((DataNodeContainer) node).getParent();
+        } else {
+            parent = null;
+        }
+
+        while (parent != null && !(parent instanceof Module)) {
+            if (parent instanceof DataSchemaNode) {
+                parent = ((DataSchemaNode) parent).getParent();
+            } else if (parent instanceof DataNodeContainer) {
+                parent = ((DataNodeContainer) parent).getParent();
+            } else {
+                parent = null;
+            }
+        }
+        return (Module) parent;
+    }
+
+    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;
+    }
+
+    @Override
+    public String getConstructorPropertyName(SchemaNode node) {
+        if (node instanceof TypeDefinition<?>) {
+            return "value";
+        } else {
+            return "";
+        }
+    }
+
 }