Merge "Added tests for yang.model.util"
[yangtools.git] / code-generator / binding-type-provider / src / main / java / org / opendaylight / yangtools / sal / binding / yang / types / TypeProviderImpl.java
index 9efd85ff6408182b37c59b44c3bf0e9a34ec4b82..d48046a48b23bc76cb174d92fe70b0e9d68f686d 100644 (file)
@@ -9,19 +9,31 @@ package org.opendaylight.yangtools.sal.binding.yang.types;
 
 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 com.google.common.base.Preconditions;
+import com.google.common.collect.Sets;
+import com.google.common.io.BaseEncoding;
+import java.io.Serializable;
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.net.URI;
-import java.util.*;
+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.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
-
 import org.apache.commons.lang3.StringEscapeUtils;
 import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil;
 import org.opendaylight.yangtools.binding.generator.util.TypeConstants;
@@ -33,6 +45,7 @@ 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.GeneratedProperty;
 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;
@@ -52,16 +65,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.type.*;
+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.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;
+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.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.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;
 
 public final class TypeProviderImpl implements TypeProvider {
+    private static final Pattern NUMBERS_PATTERN = Pattern.compile("[0-9]+\\z");
+
     /**
      * Contains the schema data red from YANG files.
      */
@@ -70,7 +103,7 @@ public final class TypeProviderImpl implements TypeProvider {
     /**
      * Map<moduleName, Map<moduleDate, Map<typeName, type>>>
      */
-    private Map<String, Map<Date, Map<String, Type>>> genTypeDefsContextMap;
+    private final Map<String, Map<Date, Map<String, Type>>> genTypeDefsContextMap;
 
     /**
      * The map which maps schema paths to JAVA <code>Type</code>.
@@ -131,7 +164,8 @@ public final class TypeProviderImpl implements TypeProvider {
      * @see TypeProvider#javaTypeForYangType(String)
      */
     @Override
-    public Type javaTypeForYangType(String type) {
+    @Deprecated
+    public Type javaTypeForYangType(final String type) {
         return BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForYangType(type);
     }
 
@@ -155,18 +189,27 @@ public final class TypeProviderImpl implements TypeProvider {
      */
     @Override
     public Type javaTypeForSchemaDefinitionType(final TypeDefinition<?> typeDefinition, final SchemaNode parentNode,
-            Restrictions r) {
+            final Restrictions r) {
         Type returnType = null;
         Preconditions.checkArgument(typeDefinition != null, "Type Definition cannot be NULL!");
-        if (typeDefinition.getQName() == null) {
-            throw new IllegalArgumentException(
-                    "Type Definition cannot have non specified QName (QName cannot be NULL!)");
-        }
-        Preconditions.checkArgument(typeDefinition.getQName().getLocalName() != null,
-                "Type Definitions Local Name cannot be NULL!");
+        Preconditions.checkArgument(typeDefinition.getQName() != null,
+                "Type Definition cannot have non specified QName (QName cannot be NULL!)");
+        String typedefName = typeDefinition.getQName().getLocalName();
+        Preconditions.checkArgument(typedefName != null, "Type Definitions Local Name cannot be NULL!");
 
         if (typeDefinition instanceof ExtendedType) {
             returnType = javaTypeForExtendedType(typeDefinition);
+            if (r != null && returnType instanceof GeneratedTransferObject) {
+                GeneratedTransferObject gto = (GeneratedTransferObject) returnType;
+                Module module = findParentModule(schemaContext, parentNode);
+                String basePackageName = moduleNamespaceToPackageName(module);
+                String packageName = packageNameForGeneratedType(basePackageName, typeDefinition.getPath());
+                String genTOName = BindingMapping.getClassName(typedefName);
+                String name = packageName + "." + genTOName;
+                if (!(returnType.getFullyQualifiedName().equals(name))) {
+                    returnType = shadedTOWithRestrictions(gto, r);
+                }
+            }
         } else {
             returnType = javaTypeForLeafrefOrIdentityRef(typeDefinition, parentNode);
             if (returnType == null) {
@@ -183,6 +226,25 @@ public final class TypeProviderImpl implements TypeProvider {
         return returnType;
     }
 
+    private GeneratedTransferObject shadedTOWithRestrictions(GeneratedTransferObject gto, Restrictions r) {
+        GeneratedTOBuilder gtob = new GeneratedTOBuilderImpl(gto.getPackageName(), gto.getName());
+        GeneratedTransferObject parent = gto.getSuperType();
+        if (parent != null) {
+            gtob.setExtendsType(parent);
+        }
+        gtob.setRestrictions(r);
+        for (GeneratedProperty gp : gto.getProperties()) {
+            GeneratedPropertyBuilder gpb = gtob.addProperty(gp.getName());
+            gpb.setValue(gp.getValue());
+            gpb.setReadOnly(gp.isReadOnly());
+            gpb.setAccessModifier(gp.getAccessModifier());
+            gpb.setReturnType(gp.getReturnType());
+            gpb.setFinal(gp.isFinal());
+            gpb.setStatic(gp.isStatic());
+        }
+        return gtob.toInstance();
+    }
+
     /**
      * Returns JAVA <code>Type</code> for instances of the type
      * <code>LeafrefTypeDefinition</code> or
@@ -192,7 +254,7 @@ public final class TypeProviderImpl implements TypeProvider {
      *            type definition which is converted to JAVA <code>Type</code>
      * @return JAVA <code>Type</code> instance for <code>typeDefinition</code>
      */
-    private Type javaTypeForLeafrefOrIdentityRef(TypeDefinition<?> typeDefinition, SchemaNode parentNode) {
+    private Type javaTypeForLeafrefOrIdentityRef(final TypeDefinition<?> typeDefinition, final SchemaNode parentNode) {
         if (typeDefinition instanceof LeafrefTypeDefinition) {
             final LeafrefTypeDefinition leafref = (LeafrefTypeDefinition) typeDefinition;
             return provideTypeForLeafref(leafref, parentNode);
@@ -212,7 +274,7 @@ public final class TypeProviderImpl implements TypeProvider {
      *            type definition which is converted to JAVA <code>Type</code>
      * @return JAVA <code>Type</code> instance for <code>typeDefinition</code>
      */
-    private Type javaTypeForExtendedType(TypeDefinition<?> typeDefinition) {
+    private Type javaTypeForExtendedType(final TypeDefinition<?> typeDefinition) {
         final String typedefName = typeDefinition.getQName().getLocalName();
         final TypeDefinition<?> baseTypeDef = baseTypeDefForExtendedType(typeDefinition);
         Type returnType = null;
@@ -261,7 +323,7 @@ public final class TypeProviderImpl implements TypeProvider {
      * @return JAVA <code>Type</code> of the identity which is refrenced through
      *         <code>idref</code>
      */
-    private Type provideTypeForIdentityref(IdentityrefTypeDefinition idref) {
+    private Type provideTypeForIdentityref(final IdentityrefTypeDefinition idref) {
         QName baseIdQName = idref.getIdentity().getQName();
         Module module = schemaContext.findModuleByNamespaceAndRevision(baseIdQName.getNamespace(),
                 baseIdQName.getRevision());
@@ -275,7 +337,7 @@ public final class TypeProviderImpl implements TypeProvider {
 
         final String basePackageName = moduleNamespaceToPackageName(module);
         final String packageName = packageNameForGeneratedType(basePackageName, identity.getPath());
-        final String genTypeName = parseToClassName(identity.getQName().getLocalName());
+        final String genTypeName = BindingMapping.getClassName(identity.getQName());
 
         Type baseType = Types.typeForClass(Class.class);
         Type paramType = Types.wildcardTypeFor(packageName, genTypeName);
@@ -338,7 +400,7 @@ public final class TypeProviderImpl implements TypeProvider {
      *             if <code>extendTypeDef</code> equal null
      */
     private TypeDefinition<?> baseTypeDefForExtendedType(final TypeDefinition<?> extendTypeDef) {
-        Preconditions.checkArgument(extendTypeDef != null, "Type Definiition reference cannot be NULL!");
+        Preconditions.checkArgument(extendTypeDef != null, "Type Definition reference cannot be NULL!");
         final TypeDefinition<?> baseTypeDef = extendTypeDef.getBaseType();
         if (baseTypeDef == null) {
             return extendTypeDef;
@@ -378,9 +440,7 @@ public final class TypeProviderImpl implements TypeProvider {
         final String strXPath = xpath.toString();
 
         if (strXPath != null) {
-            if (strXPath.contains("[")) {
-                returnType = Types.typeForClass(Object.class);
-            } else {
+            if (strXPath.indexOf('[') == -1) {
                 final Module module = findParentModule(schemaContext, parentNode);
                 if (module != null) {
                     final SchemaNode dataNode;
@@ -398,8 +458,13 @@ public final class TypeProviderImpl implements TypeProvider {
                         returnType = resolveTypeFromDataSchemaNode(dataNode);
                     }
                 }
+            } else {
+                returnType = Types.typeForClass(Object.class);
             }
         }
+        if (returnType == null) {
+            throw new IllegalArgumentException("Failed to find leafref target: " + strXPath);
+        }
         return returnType;
     }
 
@@ -478,12 +543,16 @@ public final class TypeProviderImpl implements TypeProvider {
         Preconditions.checkArgument(enumTypeDef.getQName().getLocalName() != null,
                 "Local Name in EnumTypeDefinition QName cannot be NULL!");
 
-        final String enumerationName = parseToClassName(enumName);
+        final String enumerationName = BindingMapping.getClassName(enumName);
 
         Module module = findParentModule(schemaContext, parentNode);
         final String basePackageName = moduleNamespaceToPackageName(module);
 
-        final EnumBuilder enumBuilder = new EnumerationBuilderImpl(basePackageName, enumerationName);
+        final EnumerationBuilderImpl enumBuilder = new EnumerationBuilderImpl(basePackageName, enumerationName);
+        enumBuilder.setDescription(enumTypeDef.getDescription());
+        enumBuilder.setReference(enumTypeDef.getReference());
+        enumBuilder.setModuleName(module.getName());
+        enumBuilder.setSchemaPath(enumTypeDef.getPath().getPathFromRoot());
         enumBuilder.updateEnumPairsFromEnumTypeDef(enumTypeDef);
         return enumBuilder.toInstance(null);
     }
@@ -521,9 +590,10 @@ public final class TypeProviderImpl implements TypeProvider {
                 "Local Name in EnumTypeDefinition QName cannot be NULL!");
         Preconditions.checkArgument(typeBuilder != null, "Generated Type Builder reference cannot be NULL!");
 
-        final String enumerationName = parseToClassName(enumName);
+        final String enumerationName = BindingMapping.getClassName(enumName);
 
         final EnumBuilder enumBuilder = typeBuilder.addEnumeration(enumerationName);
+        enumBuilder.setDescription(enumTypeDef.getDescription());
         enumBuilder.updateEnumPairsFromEnumTypeDef(enumTypeDef);
         return enumBuilder.toInstance(enumBuilder);
     }
@@ -571,7 +641,8 @@ public final class TypeProviderImpl implements TypeProvider {
         for (Module modul : modules) {
             modulesArray[i++] = modul;
         }
-        final List<Module> modulesSortedByDependency = ModuleDependencySort.sort(modulesArray);
+        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());
@@ -587,7 +658,6 @@ public final class TypeProviderImpl implements TypeProvider {
             if (module == null) {
                 continue;
             }
-            final String moduleName = module.getName();
             final String basePackageName = moduleNamespaceToPackageName(module);
 
             final DataNodeIterator it = new DataNodeIterator(module);
@@ -622,7 +692,6 @@ public final class TypeProviderImpl implements TypeProvider {
         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();
             final TypeDefinition<?> innerTypeDefinition = typedef.getBaseType();
             if (!(innerTypeDefinition instanceof LeafrefTypeDefinition)
@@ -630,13 +699,15 @@ public final class TypeProviderImpl implements TypeProvider {
                 Type returnType = null;
                 if (innerTypeDefinition instanceof ExtendedType) {
                     ExtendedType innerExtendedType = (ExtendedType) innerTypeDefinition;
-                    returnType = provideGeneratedTOFromExtendedType(typedef, innerExtendedType, basePackageName);
+                    returnType = provideGeneratedTOFromExtendedType(typedef, innerExtendedType, basePackageName,
+                            module.getName());
                 } else if (innerTypeDefinition instanceof UnionTypeDefinition) {
                     final GeneratedTOBuilder genTOBuilder = provideGeneratedTOBuilderForUnionTypeDef(basePackageName,
                             (UnionTypeDefinition) innerTypeDefinition, typedefName, typedef);
                     genTOBuilder.setTypedef(true);
                     genTOBuilder.setIsUnion(true);
                     addUnitsToGenTO(genTOBuilder, typedef.getUnits());
+                    makeSerializable((GeneratedTOBuilderImpl) genTOBuilder);
                     returnType = genTOBuilder.toInstance();
                     // union builder
                     GeneratedTOBuilder unionBuilder = new GeneratedTOBuilderImpl(genTOBuilder.getPackageName(),
@@ -655,20 +726,22 @@ public final class TypeProviderImpl implements TypeProvider {
                         types.add(unionBuilder.toInstance());
                     }
                 } else if (innerTypeDefinition instanceof EnumTypeDefinition) {
+                    // enums are automatically Serializable
                     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);
+                            basePackageName, bitsTypeDefinition, typedefName, module.getName());
                     genTOBuilder.setTypedef(true);
                     addUnitsToGenTO(genTOBuilder, typedef.getUnits());
+                    makeSerializable((GeneratedTOBuilderImpl) genTOBuilder);
                     returnType = genTOBuilder.toInstance();
                 } else {
                     final Type javaType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(
                             innerTypeDefinition, typedef);
-                    returnType = wrapJavaTypeIntoTO(basePackageName, typedef, javaType);
+                    returnType = wrapJavaTypeIntoTO(basePackageName, typedef, javaType, module.getName());
                 }
                 if (returnType != null) {
                     final Map<Date, Map<String, Type>> modulesByDate = genTypeDefsContextMap.get(moduleName);
@@ -695,11 +768,11 @@ public final class TypeProviderImpl implements TypeProvider {
      * @return generated transfer object which represent<code>javaType</code>
      */
     private GeneratedTransferObject wrapJavaTypeIntoTO(final String basePackageName, final TypeDefinition<?> typedef,
-            final Type javaType) {
+            final Type javaType, final String moduleName) {
         Preconditions.checkNotNull(javaType, "javaType cannot be null");
         final String propertyName = "value";
 
-        final GeneratedTOBuilder genTOBuilder = typedefToTransferObject(basePackageName, typedef);
+        final GeneratedTOBuilder genTOBuilder = typedefToTransferObject(basePackageName, typedef, moduleName);
         genTOBuilder.setRestrictions(BindingGeneratorUtil.getRestrictions(typedef));
         final GeneratedPropertyBuilder genPropBuilder = genTOBuilder.addProperty(propertyName);
         genPropBuilder.setReturnType(javaType);
@@ -712,6 +785,7 @@ public final class TypeProviderImpl implements TypeProvider {
         }
         addUnitsToGenTO(genTOBuilder, typedef.getUnits());
         genTOBuilder.setTypedef(true);
+        makeSerializable((GeneratedTOBuilderImpl) genTOBuilder);
         return genTOBuilder.toInstance();
     }
 
@@ -730,15 +804,17 @@ public final class TypeProviderImpl implements TypeProvider {
      *         builders
      */
     public GeneratedTOBuilder provideGeneratedTOBuilderForUnionTypeDef(final String basePackageName,
-            final UnionTypeDefinition typedef, String typeDefName, SchemaNode parentNode) {
+            final UnionTypeDefinition typedef, final String typeDefName, final SchemaNode parentNode) {
         final List<GeneratedTOBuilder> genTOBuilders = provideGeneratedTOBuildersForUnionTypeDef(basePackageName,
                 typedef, typeDefName, parentNode);
         GeneratedTOBuilder resultTOBuilder = null;
-        if (!genTOBuilders.isEmpty()) {
-            resultTOBuilder = genTOBuilders.remove(0);
-            for (GeneratedTOBuilder genTOBuilder : genTOBuilders) {
-                resultTOBuilder.addEnclosingTransferObject(genTOBuilder);
-            }
+        if (genTOBuilders.isEmpty()) {
+            throw new IllegalStateException("No GeneratedTOBuilder objects generated from union " + typedef);
+        }
+
+        resultTOBuilder = genTOBuilders.remove(0);
+        for (GeneratedTOBuilder genTOBuilder : genTOBuilders) {
+            resultTOBuilder.addEnclosingTransferObject(genTOBuilder);
         }
 
         final GeneratedPropertyBuilder genPropBuilder = resultTOBuilder.addProperty("value");
@@ -778,13 +854,18 @@ 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 GeneratedTOBuilder unionGenTOBuilder;
+        final GeneratedTOBuilderImpl unionGenTOBuilder;
         if (typeDefName != null && !typeDefName.isEmpty()) {
-            final String typeName = parseToClassName(typeDefName);
+            final String typeName = BindingMapping.getClassName(typeDefName);
             unionGenTOBuilder = new GeneratedTOBuilderImpl(basePackageName, typeName);
+            unionGenTOBuilder.setDescription(typedef.getDescription());
+            unionGenTOBuilder.setReference(typedef.getReference());
+            unionGenTOBuilder.setSchemaPath(typedef.getPath().getPathFromRoot());
+            unionGenTOBuilder.setModuleName(module.getName());
         } else {
-            unionGenTOBuilder = typedefToTransferObject(basePackageName, typedef);
+            unionGenTOBuilder = typedefToTransferObject(basePackageName, typedef, module.getName());
         }
 
         generatedTOBuilders.add(unionGenTOBuilder);
@@ -874,8 +955,7 @@ public final class TypeProviderImpl implements TypeProvider {
      *            list of strings with the regular expressions
      */
     private void resolveExtendedSubtypeAsUnion(final GeneratedTOBuilder parentUnionGenTOBuilder,
-            final ExtendedType unionSubtype, final List<String> regularExpressions,
-            final SchemaNode parentNode) {
+            final ExtendedType unionSubtype, final List<String> regularExpressions, final SchemaNode parentNode) {
         final String unionTypeName = unionSubtype.getQName().getLocalName();
         final Type genTO = findGenTO(unionTypeName, unionSubtype);
         if (genTO != null) {
@@ -927,7 +1007,8 @@ public final class TypeProviderImpl implements TypeProvider {
      *            generated TO builder which is converted to generated TO and
      *            stored
      */
-    private void storeGenTO(TypeDefinition<?> newTypeDef, GeneratedTOBuilder genTOBuilder, SchemaNode parentNode) {
+    private void storeGenTO(final TypeDefinition<?> newTypeDef, final GeneratedTOBuilder genTOBuilder,
+            final SchemaNode parentNode) {
         if (!(newTypeDef instanceof UnionType)) {
 
             final Module parentModule = findParentModule(schemaContext, parentNode);
@@ -975,15 +1056,21 @@ public final class TypeProviderImpl implements TypeProvider {
      * @return generated TO builder which contains data from
      *         <code>typedef</code> and <code>basePackageName</code>
      */
-    private GeneratedTOBuilder typedefToTransferObject(final String basePackageName, final TypeDefinition<?> typedef) {
+    private GeneratedTOBuilderImpl typedefToTransferObject(final String basePackageName,
+            final TypeDefinition<?> typedef, final String moduleName) {
 
         final String packageName = packageNameForGeneratedType(basePackageName, typedef.getPath());
         final String typeDefTOName = typedef.getQName().getLocalName();
 
-        if ((packageName != null) && (typedef != null) && (typeDefTOName != null)) {
-            final String genTOName = parseToClassName(typeDefTOName);
-            final GeneratedTOBuilder newType = new GeneratedTOBuilderImpl(packageName, genTOName);
-            newType.addComment(typedef.getDescription());
+        if ((packageName != null) && (typeDefTOName != null)) {
+            final String genTOName = BindingMapping.getClassName(typeDefTOName);
+            final GeneratedTOBuilderImpl newType = new GeneratedTOBuilderImpl(packageName, genTOName);
+
+            newType.setDescription(typedef.getDescription());
+            newType.setReference(typedef.getReference());
+            newType.setSchemaPath(typedef.getPath().getPathFromRoot());
+            newType.setModuleName(moduleName);
+
             return newType;
         }
         return null;
@@ -1010,7 +1097,7 @@ public final class TypeProviderImpl implements TypeProvider {
      *             </ul>
      */
     public GeneratedTOBuilder provideGeneratedTOBuilderForBitsTypeDefinition(final String basePackageName,
-            final TypeDefinition<?> typeDef, String typeDefName) {
+            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!");
@@ -1018,8 +1105,13 @@ public final class TypeProviderImpl implements TypeProvider {
         if (typeDef instanceof BitsTypeDefinition) {
             BitsTypeDefinition bitsTypeDefinition = (BitsTypeDefinition) typeDef;
 
-            final String typeName = parseToClassName(typeDefName);
-            final GeneratedTOBuilder genTOBuilder = new GeneratedTOBuilderImpl(basePackageName, typeName);
+            final String typeName = BindingMapping.getClassName(typeDefName);
+            final GeneratedTOBuilderImpl genTOBuilder = new GeneratedTOBuilderImpl(basePackageName, typeName);
+
+            genTOBuilder.setDescription(typeDef.getDescription());
+            genTOBuilder.setReference(typeDef.getReference());
+            genTOBuilder.setSchemaPath(typeDef.getPath().getPathFromRoot());
+            genTOBuilder.setModuleName(moduleName);
 
             final List<Bit> bitList = bitsTypeDefinition.getBits();
             GeneratedPropertyBuilder genPropertyBuilder;
@@ -1050,7 +1142,7 @@ public final class TypeProviderImpl implements TypeProvider {
      *             if <code>typedef</code> equals null
      *
      */
-    private List<String> resolveRegExpressionsFromTypedef(ExtendedType typedef) {
+    private List<String> resolveRegExpressionsFromTypedef(final ExtendedType typedef) {
         final List<String> regExps = new ArrayList<String>();
         Preconditions.checkArgument(typedef != null, "typedef can't be null");
         final TypeDefinition<?> strTypeDef = baseTypeDefForExtendedType(typedef);
@@ -1085,7 +1177,7 @@ public final class TypeProviderImpl implements TypeProvider {
      *             <li>if <code>regularExpressions</code> equals null</li>
      *             </ul>
      */
-    private void addStringRegExAsConstant(GeneratedTOBuilder genTOBuilder, List<String> regularExpressions) {
+    private void addStringRegExAsConstant(final GeneratedTOBuilder genTOBuilder, final List<String> regularExpressions) {
         if (genTOBuilder == null) {
             throw new IllegalArgumentException("Generated transfer object builder can't be null");
         }
@@ -1124,14 +1216,19 @@ public final class TypeProviderImpl implements TypeProvider {
      *             </ul>
      */
     private GeneratedTransferObject provideGeneratedTOFromExtendedType(final TypeDefinition<?> typedef,
-            final ExtendedType innerExtendedType, final String basePackageName) {
+            final ExtendedType 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!");
 
         final String typedefName = typedef.getQName().getLocalName();
-        final String classTypedefName = parseToClassName(typedefName);
+        final String classTypedefName = BindingMapping.getClassName(typedefName);
         final String innerTypeDef = innerExtendedType.getQName().getLocalName();
-        final GeneratedTOBuilder genTOBuilder = new GeneratedTOBuilderImpl(basePackageName, classTypedefName);
+        final GeneratedTOBuilderImpl genTOBuilder = new GeneratedTOBuilderImpl(basePackageName, classTypedefName);
+
+        genTOBuilder.setDescription(typedef.getDescription());
+        genTOBuilder.setReference(typedef.getReference());
+        genTOBuilder.setSchemaPath(typedef.getPath().getPathFromRoot());
+        genTOBuilder.setModuleName(moduleName);
         genTOBuilder.setTypedef(true);
         Restrictions r = BindingGeneratorUtil.getRestrictions(typedef);
         genTOBuilder.setRestrictions(r);
@@ -1155,10 +1252,25 @@ public final class TypeProviderImpl implements TypeProvider {
             }
         }
         addUnitsToGenTO(genTOBuilder, typedef.getUnits());
+        makeSerializable(genTOBuilder);
 
         return genTOBuilder.toInstance();
     }
 
+    /**
+     * Add {@link Serializable} to implemented interfaces of this TO. Also
+     * compute and add serialVersionUID property.
+     *
+     * @param gto
+     *            transfer object which needs to be serializable
+     */
+    private void makeSerializable(final GeneratedTOBuilderImpl gto) {
+        gto.addImplementsType(Types.typeForClass(Serializable.class));
+        GeneratedPropertyBuilder prop = new GeneratedPropertyBuilderImpl("serialVersionUID");
+        prop.setValue(Long.toString(BindingGeneratorUtil.computeDefaultSUID(gto)));
+        gto.setSUID(prop);
+    }
+
     /**
      * Finds out for each type definition how many immersion (depth) is
      * necessary to get to the base type. Every type definition is inserted to
@@ -1187,10 +1299,10 @@ public final class TypeProviderImpl implements TypeProvider {
             }
             typeDefinitionsConcreteDepth.add(unsortedTypeDefinition);
         }
-        // keys are in ascending order
-        Set<Integer> depths = typeDefinitionsDepths.keySet();
-        for (Integer depth : depths) {
-            sortedTypeDefinition.addAll(typeDefinitionsDepths.get(depth));
+
+        // SortedMap guarantees order corresponding to keys in ascending order
+        for (List<TypeDefinition<?>> v : typeDefinitionsDepths.values()) {
+            sortedTypeDefinition.addAll(v);
         }
 
         return sortedTypeDefinition;
@@ -1238,9 +1350,8 @@ public final class TypeProviderImpl implements TypeProvider {
      *            string with name of augmented node
      * @return string with the number suffix incremented by one (or 1 is added)
      */
-    private String provideAvailableNameForGenTOBuilder(String name) {
-        Pattern searchedPattern = Pattern.compile("[0-9]+\\z");
-        Matcher mtch = searchedPattern.matcher(name);
+    private String provideAvailableNameForGenTOBuilder(final String name) {
+        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;
@@ -1249,7 +1360,7 @@ public final class TypeProviderImpl implements TypeProvider {
         }
     }
 
-    public void addUnitsToGenTO(GeneratedTOBuilder to, String units) {
+    public void addUnitsToGenTO(final GeneratedTOBuilder to, final String units) {
         if (units != null && !units.isEmpty()) {
             to.addConstant(Types.STRING, "_UNITS", "\"" + units + "\"");
             GeneratedPropertyBuilder prop = new GeneratedPropertyBuilderImpl("UNITS");
@@ -1259,11 +1370,11 @@ public final class TypeProviderImpl implements TypeProvider {
     }
 
     @Override
-    public String getTypeDefaultConstruction(LeafSchemaNode node) {
+    public String getTypeDefaultConstruction(final LeafSchemaNode node) {
         return getTypeDefaultConstruction(node, node.getDefault());
     }
 
-    public String getTypeDefaultConstruction(LeafSchemaNode node, String defaultValue) {
+    public String getTypeDefaultConstruction(final LeafSchemaNode node, final String defaultValue) {
         TypeDefinition<?> type = node.getType();
         QName typeQName = type.getQName();
         TypeDefinition<?> base = baseTypeDefForExtendedType(type);
@@ -1278,9 +1389,10 @@ public final class TypeProviderImpl implements TypeProvider {
         } else if (base instanceof BitsTypeDefinition) {
             String parentName;
             String className;
-            SchemaPath nodePath = node.getPath();
             Module parent = getParentModule(node);
-            if (nodePath.getPath().size() == 1) {
+            Iterator<QName> path = node.getPath().getPathFromRoot().iterator();
+            path.next();
+            if (!(path.hasNext())) {
                 parentName = BindingMapping.getClassName((parent).getName()) + "Data";
                 String basePackageName = BindingGeneratorUtil.moduleNamespaceToPackageName(parent);
                 className = basePackageName + "." + parentName + "." + BindingMapping.getClassName(node.getQName());
@@ -1353,17 +1465,17 @@ public final class TypeProviderImpl implements TypeProvider {
             String packageName = packageNameForGeneratedType(basePackageName, type.getPath());
             String className = packageName + "." + BindingMapping.getClassName(typeQName);
             sb.insert(0, "new " + className + "(");
-            sb.insert(sb.length(), ")");
+            sb.insert(sb.length(), ')');
         }
 
         return sb.toString();
     }
 
-    private String typeToDef(Class<?> clazz, String defaultValue) {
+    private String typeToDef(final Class<?> clazz, final String defaultValue) {
         return "new " + clazz.getName() + "(\"" + defaultValue + "\")";
     }
 
-    private String binaryToDef(String defaultValue) {
+    private String binaryToDef(final String defaultValue) {
         StringBuilder sb = new StringBuilder();
         BaseEncoding en = BaseEncoding.base64();
         byte[] encoded = en.decode(defaultValue);
@@ -1374,20 +1486,25 @@ public final class TypeProviderImpl implements TypeProvider {
                 sb.append(", ");
             }
         }
-        sb.append("}");
+        sb.append('}');
         return sb.toString();
     }
 
-    private String bitsToDef(BitsTypeDefinition type, String className, String defaultValue, boolean isExt) {
+    private String bitsToDef(final BitsTypeDefinition type, final String className, final String defaultValue,
+            final boolean isExt) {
         List<Bit> bits = new ArrayList<>(type.getBits());
         Collections.sort(bits, new Comparator<Bit>() {
             @Override
-            public int compare(Bit o1, Bit o2) {
+            public int compare(final Bit o1, final Bit o2) {
                 return o1.getName().compareTo(o2.getName());
             }
         });
         StringBuilder sb = new StringBuilder();
-        sb.append(isExt ? "" : "new " + className + "(");
+        if (!isExt) {
+            sb.append("new ");
+            sb.append(className);
+            sb.append('(');
+        }
         for (int i = 0; i < bits.size(); i++) {
             if (bits.get(i).getName().equals(defaultValue)) {
                 sb.append(true);
@@ -1398,18 +1515,20 @@ public final class TypeProviderImpl implements TypeProvider {
                 sb.append(", ");
             }
         }
-        sb.append(isExt ? "" : ")");
+        if (!isExt) {
+            sb.append(')');
+        }
         return sb.toString();
     }
 
-    private Module getParentModule(SchemaNode node) {
-        QName qname = node.getPath().getPath().get(0);
+    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);
     }
 
-    private String leafrefToDef(LeafSchemaNode parentNode, LeafrefTypeDefinition leafrefType) {
+    private String leafrefToDef(final LeafSchemaNode parentNode, final 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!");
@@ -1418,9 +1537,7 @@ public final class TypeProviderImpl implements TypeProvider {
         final String strXPath = xpath.toString();
 
         if (strXPath != null) {
-            if (strXPath.contains("[")) {
-                return "new java.lang.Object()";
-            } else {
+            if (strXPath.indexOf('[') == -1) {
                 final Module module = findParentModule(schemaContext, parentNode);
                 if (module != null) {
                     final SchemaNode dataNode;
@@ -1432,13 +1549,15 @@ public final class TypeProviderImpl implements TypeProvider {
                     String result = getTypeDefaultConstruction((LeafSchemaNode) dataNode, parentNode.getDefault());
                     return result;
                 }
+            } else {
+                return "new java.lang.Object()";
             }
         }
 
         return null;
     }
 
-    private String unionToDef(LeafSchemaNode node) {
+    private String unionToDef(final LeafSchemaNode node) {
         String parentName;
         String className;
 
@@ -1458,7 +1577,7 @@ public final class TypeProviderImpl implements TypeProvider {
                     List<Module> modulesList = new ArrayList<>(modules);
                     Collections.sort(modulesList, new Comparator<Module>() {
                         @Override
-                        public int compare(Module o1, Module o2) {
+                        public int compare(final Module o1, final Module o2) {
                             return o1.getRevision().compareTo(o2.getRevision());
                         }
                     });
@@ -1471,9 +1590,9 @@ public final class TypeProviderImpl implements TypeProvider {
             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);
+            Iterator<QName> path = node.getPath().getPathFromRoot().iterator();
+            QName first = path.next();
+            if (!(path.hasNext())) {
                 URI namespace = first.getNamespace();
                 Date revision = first.getRevision();
                 Module parent = schemaContext.findModuleByNamespaceAndRevision(namespace, revision);
@@ -1481,7 +1600,6 @@ public final class TypeProviderImpl implements TypeProvider {
                 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);
@@ -1493,19 +1611,18 @@ public final class TypeProviderImpl implements TypeProvider {
         return union(className, node.getDefault(), node);
     }
 
-    private String union(String className, String defaultValue, LeafSchemaNode node) {
+    private String union(final String className, final String defaultValue, final LeafSchemaNode node) {
         StringBuilder sb = new StringBuilder();
-        sb.append("new " + className + "(");
-        sb.append("\"");
+        sb.append("new ");
+        sb.append(className);
+        sb.append("(\"");
         sb.append(defaultValue);
-        sb.append("\"");
-        sb.append(".toCharArray()");
-        sb.append(")");
+        sb.append("\".toCharArray())");
         return sb.toString();
     }
 
     @Override
-    public String getConstructorPropertyName(SchemaNode node) {
+    public String getConstructorPropertyName(final SchemaNode node) {
         if (node instanceof TypeDefinition<?>) {
             return "value";
         } else {
@@ -1514,7 +1631,7 @@ public final class TypeProviderImpl implements TypeProvider {
     }
 
     @Override
-    public String getParamNameFromType(TypeDefinition<?> type) {
+    public String getParamNameFromType(final TypeDefinition<?> type) {
         return BindingGeneratorUtil.parseToValidParamName(type.getQName().getLocalName());
     }