Added support for parsing yang models with already resolved context.
[controller.git] / opendaylight / sal / yang-prototype / code-generator / yang-model-parser-impl / src / main / java / org / opendaylight / controller / yang / parser / util / ParserUtils.java
index d38bc5e7adf22f74f6678e9614d38e2872a8099d..ba3599ca97b8f86378162845684f3cb83da79c55 100644 (file)
@@ -7,14 +7,33 @@
  */
 package org.opendaylight.controller.yang.parser.util;
 
-import java.lang.reflect.Method;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
+import java.util.TreeMap;
 
 import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.AnyXmlSchemaNode;
+import org.opendaylight.controller.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.controller.yang.model.api.ChoiceNode;
+import org.opendaylight.controller.yang.model.api.ConstraintDefinition;
+import org.opendaylight.controller.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.controller.yang.model.api.DataNodeContainer;
+import org.opendaylight.controller.yang.model.api.DataSchemaNode;
+import org.opendaylight.controller.yang.model.api.GroupingDefinition;
+import org.opendaylight.controller.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.controller.yang.model.api.LeafSchemaNode;
+import org.opendaylight.controller.yang.model.api.ListSchemaNode;
+import org.opendaylight.controller.yang.model.api.Module;
 import org.opendaylight.controller.yang.model.api.ModuleImport;
 import org.opendaylight.controller.yang.model.api.MustDefinition;
+import org.opendaylight.controller.yang.model.api.NotificationDefinition;
+import org.opendaylight.controller.yang.model.api.RevisionAwareXPath;
+import org.opendaylight.controller.yang.model.api.SchemaContext;
+import org.opendaylight.controller.yang.model.api.SchemaNode;
 import org.opendaylight.controller.yang.model.api.SchemaPath;
 import org.opendaylight.controller.yang.model.api.TypeDefinition;
 import org.opendaylight.controller.yang.model.api.type.BinaryTypeDefinition;
@@ -49,8 +68,14 @@ import org.opendaylight.controller.yang.model.util.Int64;
 import org.opendaylight.controller.yang.model.util.Int8;
 import org.opendaylight.controller.yang.model.util.Leafref;
 import org.opendaylight.controller.yang.model.util.StringType;
+import org.opendaylight.controller.yang.model.util.Uint16;
+import org.opendaylight.controller.yang.model.util.Uint32;
+import org.opendaylight.controller.yang.model.util.Uint64;
+import org.opendaylight.controller.yang.model.util.Uint8;
 import org.opendaylight.controller.yang.model.util.UnionType;
+import org.opendaylight.controller.yang.model.util.UnknownType;
 import org.opendaylight.controller.yang.parser.builder.api.AugmentationSchemaBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.AugmentationTargetBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.Builder;
 import org.opendaylight.controller.yang.parser.builder.api.DataNodeContainerBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.DataSchemaNodeBuilder;
@@ -61,15 +86,23 @@ import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder
 import org.opendaylight.controller.yang.parser.builder.api.UsesNodeBuilder;
 import org.opendaylight.controller.yang.parser.builder.impl.AnyXmlBuilder;
 import org.opendaylight.controller.yang.parser.builder.impl.ChoiceBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.ChoiceBuilder.ChoiceNodeImpl;
 import org.opendaylight.controller.yang.parser.builder.impl.ChoiceCaseBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.ChoiceCaseBuilder.ChoiceCaseNodeImpl;
 import org.opendaylight.controller.yang.parser.builder.impl.ConstraintsBuilder;
 import org.opendaylight.controller.yang.parser.builder.impl.ContainerSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.ContainerSchemaNodeBuilder.ContainerSchemaNodeImpl;
 import org.opendaylight.controller.yang.parser.builder.impl.GroupingBuilderImpl;
 import org.opendaylight.controller.yang.parser.builder.impl.LeafListSchemaNodeBuilder;
 import org.opendaylight.controller.yang.parser.builder.impl.LeafSchemaNodeBuilder;
 import org.opendaylight.controller.yang.parser.builder.impl.ListSchemaNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.ListSchemaNodeBuilder.ListSchemaNodeImpl;
 import org.opendaylight.controller.yang.parser.builder.impl.ModuleBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.NotificationBuilder;
+import org.opendaylight.controller.yang.parser.builder.impl.NotificationBuilder.NotificationDefinitionImpl;
+import org.opendaylight.controller.yang.parser.builder.impl.RpcDefinitionBuilder;
 import org.opendaylight.controller.yang.parser.builder.impl.TypeDefinitionBuilderImpl;
+import org.opendaylight.controller.yang.parser.builder.impl.UnionTypeBuilder;
 import org.opendaylight.controller.yang.parser.builder.impl.UnknownSchemaNodeBuilder;
 import org.opendaylight.controller.yang.parser.builder.impl.UsesNodeBuilderImpl;
 
@@ -80,15 +113,14 @@ public final class ParserUtils {
 
     /**
      * Get module import referenced by given prefix.
-     * 
+     *
      * @param builder
      *            module to search
      * @param prefix
      *            prefix associated with import
      * @return ModuleImport based on given prefix
      */
-    public static ModuleImport getModuleImport(final ModuleBuilder builder,
-            final String prefix) {
+    public static ModuleImport getModuleImport(final ModuleBuilder builder, final String prefix) {
         ModuleImport moduleImport = null;
         for (ModuleImport mi : builder.getModuleImports()) {
             if (mi.getPrefix().equals(prefix)) {
@@ -99,9 +131,170 @@ public final class ParserUtils {
         return moduleImport;
     }
 
+    /**
+     * Find dependent module based on given prefix
+     *
+     * @param modules
+     *            all available modules
+     * @param module
+     *            current module
+     * @param prefix
+     *            target module prefix
+     * @param line
+     *            current line in yang model
+     * @return
+     */
+    public static ModuleBuilder findDependentModuleBuilder(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
+            final ModuleBuilder module, final String prefix, final int line) {
+        ModuleBuilder dependentModule = null;
+        Date dependentModuleRevision = null;
+
+        if (prefix.equals(module.getPrefix())) {
+            dependentModule = module;
+        } else {
+            final ModuleImport dependentModuleImport = getModuleImport(module, prefix);
+            if (dependentModuleImport == null) {
+                throw new YangParseException(module.getName(), line, "No import found with prefix '" + prefix + "'.");
+            }
+            final String dependentModuleName = dependentModuleImport.getModuleName();
+            dependentModuleRevision = dependentModuleImport.getRevision();
+
+            final TreeMap<Date, ModuleBuilder> moduleBuildersByRevision = modules.get(dependentModuleName);
+            if (moduleBuildersByRevision == null) {
+                return null;
+            }
+            if (dependentModuleRevision == null) {
+                dependentModule = moduleBuildersByRevision.lastEntry().getValue();
+            } else {
+                dependentModule = moduleBuildersByRevision.get(dependentModuleRevision);
+            }
+        }
+        return dependentModule;
+    }
+
+    /**
+     * Find module from context based on prefix.
+     *
+     * @param context
+     *            schema context
+     * @param currentModule
+     *            current module
+     * @param prefix
+     *            current prefix used to reference dependent module
+     * @param line
+     *            current line in yang model
+     * @return module based on given prefix if found in context, null otherwise
+     */
+    public static Module findModuleFromContext(final SchemaContext context, final ModuleBuilder currentModule,
+            final String prefix, final int line) {
+        TreeMap<Date, Module> modulesByRevision = new TreeMap<Date, Module>();
+
+        Date dependentModuleRevision = null;
+
+        final ModuleImport dependentModuleImport = ParserUtils.getModuleImport(currentModule, prefix);
+        if (dependentModuleImport == null) {
+            throw new YangParseException(currentModule.getName(), line, "No import found with prefix '" + prefix + "'.");
+        }
+        final String dependentModuleName = dependentModuleImport.getModuleName();
+        dependentModuleRevision = dependentModuleImport.getRevision();
+
+        for (Module contextModule : context.getModules()) {
+            if (contextModule.getName().equals(dependentModuleName)) {
+                Date revision = contextModule.getRevision();
+                if (revision == null) {
+                    revision = new Date(0L);
+                }
+                modulesByRevision.put(revision, contextModule);
+                break;
+            }
+        }
+
+        Module result = null;
+        if (dependentModuleRevision == null) {
+            result = modulesByRevision.get(modulesByRevision.firstKey());
+        } else {
+            result = modulesByRevision.get(dependentModuleRevision);
+        }
+
+        return result;
+    }
+
+    /**
+     * Find grouping by name.
+     *
+     * @param groupings
+     *            collection of grouping builders to search
+     * @param name
+     *            name of grouping
+     * @return grouping with given name if present in collection, null otherwise
+     */
+    public static GroupingBuilder findGroupingBuilder(Set<GroupingBuilder> groupings, String name) {
+        for (GroupingBuilder grouping : groupings) {
+            if (grouping.getQName().getLocalName().equals(name)) {
+                return grouping;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Find grouping by name.
+     *
+     * @param groupings
+     *            collection of grouping definitions to search
+     * @param name
+     *            name of grouping
+     * @return grouping with given name if present in collection, null otherwise
+     */
+    public static GroupingDefinition findGroupingDefinition(Set<GroupingDefinition> groupings, String name) {
+        for (GroupingDefinition grouping : groupings) {
+            if (grouping.getQName().getLocalName().equals(name)) {
+                return grouping;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Search types for type with given name.
+     *
+     * @param types
+     *            types to search
+     * @param name
+     *            name of type
+     * @return type with given name if present in collection, null otherwise
+     */
+    public static TypeDefinitionBuilder findTypedefBuilderByName(Set<TypeDefinitionBuilder> types, String name) {
+        for (TypeDefinitionBuilder td : types) {
+            if (td.getQName().getLocalName().equals(name)) {
+                return td;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Find type by name.
+     *
+     * @param types
+     *            collection of types
+     * @param typeName
+     *            type name
+     * @return type with given name if it is present in collection, null
+     *         otherwise
+     */
+    public static TypeDefinition<?> findTypeByName(Set<TypeDefinition<?>> types, String typeName) {
+        for (TypeDefinition<?> type : types) {
+            if (type.getQName().getLocalName().equals(typeName)) {
+                return type;
+            }
+        }
+        return null;
+    }
+
     /**
      * Parse uses path.
-     * 
+     *
      * @param usesPath
      *            as String
      * @return SchemaPath from given String
@@ -117,8 +310,7 @@ public final class ParserUtils {
                 if (splittedElement.length == 1) {
                     name = new QName(null, null, null, splittedElement[0]);
                 } else {
-                    name = new QName(null, null, splittedElement[0],
-                            splittedElement[1]);
+                    name = new QName(null, null, splittedElement[0], splittedElement[1]);
                 }
                 path.add(name);
             }
@@ -126,15 +318,103 @@ public final class ParserUtils {
         return new SchemaPath(path, absolute);
     }
 
+    /**
+     * Pull restriction from type and add them to constraints.
+     *
+     * @param type
+     * @param constraints
+     */
+    public static void mergeConstraints(final TypeDefinition<?> type, final TypeConstraints constraints) {
+        if (type instanceof DecimalTypeDefinition) {
+            constraints.addRanges(((DecimalTypeDefinition) type).getRangeStatements());
+            constraints.addFractionDigits(((DecimalTypeDefinition) type).getFractionDigits());
+        } else if (type instanceof IntegerTypeDefinition) {
+            constraints.addRanges(((IntegerTypeDefinition) type).getRangeStatements());
+        } else if (type instanceof StringTypeDefinition) {
+            constraints.addPatterns(((StringTypeDefinition) type).getPatterns());
+            constraints.addLengths(((StringTypeDefinition) type).getLengthStatements());
+        } else if (type instanceof BinaryTypeDefinition) {
+            constraints.addLengths(((BinaryTypeDefinition) type).getLengthConstraints());
+        }
+    }
+
+    /**
+     * Find node in grouping by name.
+     *
+     * @param grouping
+     *            grouping to search
+     * @param refineNodeName
+     *            name of node
+     * @return builder of node with given name if present in grouping, null
+     *         otherwise
+     */
+    public static Builder findRefineTargetBuilder(final GroupingBuilder grouping, final String refineNodeName) {
+        // search child nodes
+        Builder result = grouping.getChildNode(refineNodeName);
+        // search groupings
+        if (result == null) {
+            Set<GroupingBuilder> grps = grouping.getGroupings();
+            for (GroupingBuilder gr : grps) {
+                if (gr.getQName().getLocalName().equals(refineNodeName)) {
+                    result = gr;
+                    break;
+                }
+            }
+        }
+        // search typedefs
+        if (result == null) {
+            Set<TypeDefinitionBuilder> typedefs = grouping.getTypeDefinitions();
+            for (TypeDefinitionBuilder typedef : typedefs) {
+                if (typedef.getQName().getLocalName().equals(refineNodeName)) {
+                    result = typedef;
+                    break;
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Find node in grouping by name.
+     *
+     * @param builder
+     *            grouping to search
+     * @param refineNodeName
+     *            name of node
+     * @return node with given name if present in grouping, null otherwise
+     */
+    public static Object findRefineTargetNode(final GroupingDefinition builder, final String refineNodeName) {
+        Object result = builder.getDataChildByName(refineNodeName);
+        if (result == null) {
+            Set<GroupingDefinition> grps = builder.getGroupings();
+            for (GroupingDefinition gr : grps) {
+                if (gr.getQName().getLocalName().equals(refineNodeName)) {
+                    result = gr;
+                    break;
+                }
+            }
+        }
+        if (result == null) {
+            Set<TypeDefinition<?>> typedefs = builder.getTypeDefinitions();
+            for (TypeDefinition<?> typedef : typedefs) {
+                if (typedef.getQName().getLocalName().equals(refineNodeName)) {
+                    result = typedef;
+                    break;
+                }
+            }
+        }
+        return result;
+    }
+
     /**
      * Add all augment's child nodes to given target.
-     * 
+     *
      * @param augment
+     *            builder of augment statement
      * @param target
+     *            augmentation target node
      */
-    public static void fillAugmentTarget(
-            final AugmentationSchemaBuilder augment,
-            final DataNodeContainerBuilder target) {
+    public static void fillAugmentTarget(final AugmentationSchemaBuilder augment, final DataNodeContainerBuilder target) {
         for (DataSchemaNodeBuilder builder : augment.getChildNodes()) {
             builder.setAugmenting(true);
             correctAugmentChildPath(builder, target.getPath());
@@ -142,8 +422,15 @@ public final class ParserUtils {
         }
     }
 
-    public static void fillAugmentTarget(
-            final AugmentationSchemaBuilder augment, final ChoiceBuilder target) {
+    /**
+     * Add all augment's child nodes to given target.
+     *
+     * @param augment
+     *            builder of augment statement
+     * @param target
+     *            augmentation target choice node
+     */
+    public static void fillAugmentTarget(final AugmentationSchemaBuilder augment, final ChoiceBuilder target) {
         for (DataSchemaNodeBuilder builder : augment.getChildNodes()) {
             builder.setAugmenting(true);
             correctAugmentChildPath(builder, target.getPath());
@@ -151,21 +438,16 @@ public final class ParserUtils {
         }
     }
 
-    private static void correctAugmentChildPath(
-            final DataSchemaNodeBuilder childNode,
-            final SchemaPath parentSchemaPath) {
-
+    private static void correctAugmentChildPath(final DataSchemaNodeBuilder childNode, final SchemaPath parentSchemaPath) {
         // set correct path
-        List<QName> targetNodePath = new ArrayList<QName>(
-                parentSchemaPath.getPath());
+        List<QName> targetNodePath = new ArrayList<QName>(parentSchemaPath.getPath());
         targetNodePath.add(childNode.getQName());
         childNode.setPath(new SchemaPath(targetNodePath, true));
 
         // set correct path for all child nodes
         if (childNode instanceof DataNodeContainerBuilder) {
             DataNodeContainerBuilder dataNodeContainer = (DataNodeContainerBuilder) childNode;
-            for (DataSchemaNodeBuilder child : dataNodeContainer
-                    .getChildNodes()) {
+            for (DataSchemaNodeBuilder child : dataNodeContainer.getChildNodes()) {
                 correctAugmentChildPath(child, childNode.getPath());
             }
         }
@@ -179,14 +461,13 @@ public final class ParserUtils {
 
     /**
      * Repair schema path of node type.
-     * 
+     *
      * @param node
      *            node which contains type statement
      * @param parentSchemaPath
      *            schema path of parent node
      */
-    private static void correctTypeAwareNodePath(
-            TypeAwareBuilder node, SchemaPath parentSchemaPath) {
+    private static void correctTypeAwareNodePath(final TypeAwareBuilder node, final SchemaPath parentSchemaPath) {
         final QName nodeBuilderQName = node.getQName();
         final TypeDefinition<?> nodeType = node.getType();
 
@@ -198,11 +479,7 @@ public final class ParserUtils {
         if (nodeType != null) {
             if (nodeType instanceof ExtendedType) {
                 ExtendedType et = (ExtendedType) nodeType;
-                if (nodeType
-                        .getQName()
-                        .getLocalName()
-                        .equals(nodeType.getBaseType().getQName()
-                                .getLocalName())) {
+                if (nodeType.getQName().getLocalName().equals(nodeType.getBaseType().getQName().getLocalName())) {
                     fd = et.getFractionDigits();
                     lengths = et.getLengths();
                     patterns = et.getPatterns();
@@ -212,8 +489,7 @@ public final class ParserUtils {
                     }
                 }
             }
-            TypeDefinition<?> newType = createCorrectTypeDefinition(
-                    parentSchemaPath, nodeBuilderQName, nodeType);
+            TypeDefinition<?> newType = createCorrectTypeDefinition(parentSchemaPath, nodeBuilderQName, nodeType);
             node.setType(newType);
         } else {
             TypeDefinitionBuilder nodeBuilderTypedef = node.getTypedef();
@@ -226,11 +502,9 @@ public final class ParserUtils {
             String tdbTypeName = nodeBuilderTypedef.getQName().getLocalName();
             String baseTypeName = null;
             if (nodeBuilderTypedef.getType() == null) {
-                baseTypeName = nodeBuilderTypedef.getTypedef().getQName()
-                        .getLocalName();
+                baseTypeName = nodeBuilderTypedef.getTypedef().getQName().getLocalName();
             } else {
-                baseTypeName = nodeBuilderTypedef.getType().getQName()
-                        .getLocalName();
+                baseTypeName = nodeBuilderTypedef.getType().getQName().getLocalName();
             }
             if (!(tdbTypeName.equals(baseTypeName))) {
                 return;
@@ -240,8 +514,7 @@ public final class ParserUtils {
                 return;
             }
 
-            SchemaPath newSchemaPath = createNewSchemaPath(
-                    nodeBuilderTypedef.getPath(), nodeBuilderQName,
+            SchemaPath newSchemaPath = createNewSchemaPath(nodeBuilderTypedef.getPath(), nodeBuilderQName,
                     nodeBuilderTypedef.getQName());
             nodeBuilderTypedef.setPath(newSchemaPath);
         }
@@ -249,7 +522,7 @@ public final class ParserUtils {
 
     /**
      * Check if there are some constraints.
-     * 
+     *
      * @param fd
      *            fraction digits
      * @param lengths
@@ -260,12 +533,9 @@ public final class ParserUtils {
      *            range constraints
      * @return true, if any of constraints are present, false otherwise
      */
-    private static boolean hasConstraints(final Integer fd,
-            final List<LengthConstraint> lengths,
-            final List<PatternConstraint> patterns,
-            final List<RangeConstraint> ranges) {
-        if (fd == null && (lengths == null || lengths.isEmpty())
-                && (patterns == null || patterns.isEmpty())
+    private static boolean hasConstraints(final Integer fd, final List<LengthConstraint> lengths,
+            final List<PatternConstraint> patterns, final List<RangeConstraint> ranges) {
+        if (fd == null && (lengths == null || lengths.isEmpty()) && (patterns == null || patterns.isEmpty())
                 && (ranges == null || ranges.isEmpty())) {
             return false;
         } else {
@@ -273,122 +543,106 @@ public final class ParserUtils {
         }
     }
 
-    private static TypeDefinition<?> createCorrectTypeDefinition(
-            SchemaPath parentSchemaPath, QName nodeQName,
+    private static TypeDefinition<?> createCorrectTypeDefinition(SchemaPath parentSchemaPath, QName nodeQName,
             TypeDefinition<?> nodeType) {
+        QName nodeTypeQName = nodeType.getQName();
+        SchemaPath newSchemaPath = createNewSchemaPath(parentSchemaPath, nodeQName, nodeTypeQName);
         TypeDefinition<?> result = null;
-        SchemaPath newSchemaPath = null;
+
         if (nodeType != null) {
             if (nodeType instanceof BinaryTypeDefinition) {
                 BinaryTypeDefinition binType = (BinaryTypeDefinition) nodeType;
-                newSchemaPath = createNewSchemaPath(parentSchemaPath,
-                        nodeQName, binType.getQName());
-                List<Byte> bytes = (List<Byte>) binType.getDefaultValue();
+
+                // List<Byte> bytes = (List<Byte>) binType.getDefaultValue();
+                // workaround to get rid of 'Unchecked cast' warning
+                List<Byte> bytes = new ArrayList<Byte>();
+                Object defaultValue = binType.getDefaultValue();
+                if (defaultValue instanceof List) {
+                    for (Object o : List.class.cast(defaultValue)) {
+                        if (o instanceof Byte) {
+                            bytes.add((Byte) o);
+                        }
+                    }
+                }
                 result = new BinaryType(newSchemaPath, bytes);
             } else if (nodeType instanceof BitsTypeDefinition) {
                 BitsTypeDefinition bitsType = (BitsTypeDefinition) nodeType;
-                newSchemaPath = createNewSchemaPath(parentSchemaPath,
-                        nodeQName, nodeType.getQName());
                 result = new BitsType(newSchemaPath, bitsType.getBits());
             } else if (nodeType instanceof BooleanTypeDefinition) {
-                BooleanTypeDefinition booleanType = (BooleanTypeDefinition) nodeType;
-                newSchemaPath = createNewSchemaPath(parentSchemaPath,
-                        nodeQName, booleanType.getQName());
                 result = new BooleanType(newSchemaPath);
             } else if (nodeType instanceof DecimalTypeDefinition) {
                 DecimalTypeDefinition decimalType = (DecimalTypeDefinition) nodeType;
-                newSchemaPath = createNewSchemaPath(parentSchemaPath,
-                        nodeQName, decimalType.getQName());
-                result = new Decimal64(newSchemaPath,
-                        decimalType.getFractionDigits());
+                result = new Decimal64(newSchemaPath, decimalType.getFractionDigits());
             } else if (nodeType instanceof EmptyTypeDefinition) {
-                newSchemaPath = createNewSchemaPath(parentSchemaPath,
-                        nodeQName, nodeType.getQName());
                 result = new EmptyType(newSchemaPath);
             } else if (nodeType instanceof EnumTypeDefinition) {
                 EnumTypeDefinition enumType = (EnumTypeDefinition) nodeType;
-                newSchemaPath = createNewSchemaPath(parentSchemaPath,
-                        nodeQName, enumType.getQName());
-                result = new EnumerationType(newSchemaPath,
-                        (EnumPair) enumType.getDefaultValue(),
-                        enumType.getValues());
+                result = new EnumerationType(newSchemaPath, (EnumPair) enumType.getDefaultValue(), enumType.getValues());
             } else if (nodeType instanceof IdentityrefTypeDefinition) {
                 IdentityrefTypeDefinition idrefType = (IdentityrefTypeDefinition) nodeType;
-                newSchemaPath = createNewSchemaPath(parentSchemaPath,
-                        nodeQName, idrefType.getQName());
-                result = new IdentityrefType(idrefType.getIdentity(),
-                        newSchemaPath);
+                result = new IdentityrefType(idrefType.getIdentity(), newSchemaPath);
             } else if (nodeType instanceof InstanceIdentifierTypeDefinition) {
                 InstanceIdentifierTypeDefinition instIdType = (InstanceIdentifierTypeDefinition) nodeType;
-                newSchemaPath = createNewSchemaPath(parentSchemaPath,
-                        nodeQName, instIdType.getQName());
-                return new InstanceIdentifier(newSchemaPath,
-                        instIdType.getPathStatement(),
+                return new InstanceIdentifier(newSchemaPath, instIdType.getPathStatement(),
                         instIdType.requireInstance());
             } else if (nodeType instanceof StringTypeDefinition) {
-                result = createNewStringType(parentSchemaPath, nodeQName,
-                        (StringTypeDefinition) nodeType);
+                result = createNewStringType(parentSchemaPath, nodeQName, (StringTypeDefinition) nodeType);
             } else if (nodeType instanceof IntegerTypeDefinition) {
-                result = createNewIntType(parentSchemaPath, nodeQName,
-                        (IntegerTypeDefinition) nodeType);
+                result = createNewIntType(parentSchemaPath, nodeQName, (IntegerTypeDefinition) nodeType);
             } else if (nodeType instanceof UnsignedIntegerTypeDefinition) {
-                result = createNewUintType(parentSchemaPath, nodeQName,
-                        (UnsignedIntegerTypeDefinition) nodeType);
+                result = createNewUintType(parentSchemaPath, nodeQName, (UnsignedIntegerTypeDefinition) nodeType);
             } else if (nodeType instanceof LeafrefTypeDefinition) {
-                newSchemaPath = createNewSchemaPath(parentSchemaPath,
-                        nodeQName, nodeType.getQName());
-                result = new Leafref(newSchemaPath,
-                        ((LeafrefTypeDefinition) nodeType).getPathStatement());
+                result = new Leafref(newSchemaPath, ((LeafrefTypeDefinition) nodeType).getPathStatement());
             } else if (nodeType instanceof UnionTypeDefinition) {
                 UnionTypeDefinition unionType = (UnionTypeDefinition) nodeType;
-                newSchemaPath = createNewSchemaPath(parentSchemaPath,
-                        nodeQName, unionType.getQName());
                 return new UnionType(newSchemaPath, unionType.getTypes());
             } else if (nodeType instanceof ExtendedType) {
                 ExtendedType extType = (ExtendedType) nodeType;
-                newSchemaPath = createNewSchemaPath(parentSchemaPath,
-                        nodeQName, extType.getQName());
-                result = createNewExtendedType(newSchemaPath, extType);
+                result = createNewExtendedType(extType, newSchemaPath);
             }
         }
         return result;
     }
 
-    private static TypeDefinition<?> createNewExtendedType(
-            SchemaPath newSchemaPath, ExtendedType oldExtendedType) {
-        QName qname = oldExtendedType.getQName();
-        TypeDefinition<?> baseType = oldExtendedType.getBaseType();
-        String desc = oldExtendedType.getDescription();
-        String ref = oldExtendedType.getReference();
-        ExtendedType.Builder builder = new ExtendedType.Builder(qname,
-                baseType, desc, ref, newSchemaPath);
-        builder.status(oldExtendedType.getStatus());
-        builder.lengths(oldExtendedType.getLengths());
-        builder.patterns(oldExtendedType.getPatterns());
-        builder.ranges(oldExtendedType.getRanges());
-        builder.fractionDigits(oldExtendedType.getFractionDigits());
-        builder.unknownSchemaNodes(oldExtendedType.getUnknownSchemaNodes());
+    /**
+     * Create new ExtendedType based on given type and with schema path.
+     *
+     * @param newPath
+     *            schema path for new type
+     * @param oldType
+     *            type based
+     * @return
+     */
+    private static ExtendedType createNewExtendedType(final ExtendedType oldType, final SchemaPath newPath) {
+        QName qname = oldType.getQName();
+        TypeDefinition<?> baseType = oldType.getBaseType();
+        String desc = oldType.getDescription();
+        String ref = oldType.getReference();
+        ExtendedType.Builder builder = new ExtendedType.Builder(qname, baseType, desc, ref, newPath);
+        builder.status(oldType.getStatus());
+        builder.lengths(oldType.getLengths());
+        builder.patterns(oldType.getPatterns());
+        builder.ranges(oldType.getRanges());
+        builder.fractionDigits(oldType.getFractionDigits());
+        builder.unknownSchemaNodes(oldType.getUnknownSchemaNodes());
         return builder.build();
     }
 
-    private static TypeDefinition<?> createNewStringType(SchemaPath schemaPath,
-            QName nodeQName, StringTypeDefinition nodeType) {
-        List<QName> path = schemaPath.getPath();
-        List<QName> newPath = new ArrayList<QName>(path);
+    private static StringTypeDefinition createNewStringType(final SchemaPath schemaPath, final QName nodeQName,
+            final StringTypeDefinition nodeType) {
+        final List<QName> path = schemaPath.getPath();
+        final List<QName> newPath = new ArrayList<QName>(path);
         newPath.add(nodeQName);
         newPath.add(nodeType.getQName());
-        SchemaPath newSchemaPath = new SchemaPath(newPath,
-                schemaPath.isAbsolute());
-
+        final SchemaPath newSchemaPath = new SchemaPath(newPath, schemaPath.isAbsolute());
         return new StringType(newSchemaPath);
     }
 
-    private static TypeDefinition<?> createNewIntType(SchemaPath schemaPath,
-            QName nodeQName, IntegerTypeDefinition type) {
-        QName typeQName = type.getQName();
-        SchemaPath newSchemaPath = createNewSchemaPath(schemaPath, nodeQName,
-                typeQName);
-        String localName = typeQName.getLocalName();
+    private static IntegerTypeDefinition createNewIntType(final SchemaPath schemaPath, final QName nodeQName,
+            final IntegerTypeDefinition type) {
+        final QName typeQName = type.getQName();
+        final SchemaPath newSchemaPath = createNewSchemaPath(schemaPath, nodeQName, typeQName);
+        final String localName = typeQName.getLocalName();
 
         if ("int8".equals(localName)) {
             return new Int8(newSchemaPath);
@@ -403,335 +657,55 @@ public final class ParserUtils {
         }
     }
 
-    private static TypeDefinition<?> createNewUintType(SchemaPath schemaPath,
-            QName nodeQName, UnsignedIntegerTypeDefinition type) {
-        QName typeQName = type.getQName();
-        SchemaPath newSchemaPath = createNewSchemaPath(schemaPath, nodeQName,
-                typeQName);
-        String localName = typeQName.getLocalName();
+    private static UnsignedIntegerTypeDefinition createNewUintType(final SchemaPath schemaPath, final QName nodeQName,
+            final UnsignedIntegerTypeDefinition type) {
+        final QName typeQName = type.getQName();
+        final SchemaPath newSchemaPath = createNewSchemaPath(schemaPath, nodeQName, typeQName);
+        final String localName = typeQName.getLocalName();
 
         if ("uint8".equals(localName)) {
-            return new Int8(newSchemaPath);
+            return new Uint8(newSchemaPath);
         } else if ("uint16".equals(localName)) {
-            return new Int16(newSchemaPath);
+            return new Uint16(newSchemaPath);
         } else if ("uint32".equals(localName)) {
-            return new Int32(newSchemaPath);
+            return new Uint32(newSchemaPath);
         } else if ("uint64".equals(localName)) {
-            return new Int64(newSchemaPath);
+            return new Uint64(newSchemaPath);
         } else {
             return null;
         }
     }
 
-    private static SchemaPath createNewSchemaPath(SchemaPath schemaPath,
-            QName currentQName, QName qname) {
+    private static SchemaPath createNewSchemaPath(final SchemaPath schemaPath, final QName currentQName,
+            final QName qname) {
         List<QName> newPath = new ArrayList<QName>(schemaPath.getPath());
         newPath.add(currentQName);
         newPath.add(qname);
         return new SchemaPath(newPath, schemaPath.isAbsolute());
     }
 
-    public static void refineLeaf(LeafSchemaNodeBuilder leaf,
-            RefineHolder refine, int line) {
-        String defaultStr = refine.getDefaultStr();
-        Boolean mandatory = refine.isMandatory();
-        MustDefinition must = refine.getMust();
-        List<UnknownSchemaNodeBuilder> unknownNodes = refine.getUnknownNodes();
-
-        if (defaultStr != null && !("".equals(defaultStr))) {
-            leaf.setDefaultStr(defaultStr);
-        }
-        if (mandatory != null) {
-            leaf.getConstraints().setMandatory(mandatory);
-        }
-        if (must != null) {
-            leaf.getConstraints().addMustDefinition(must);
-        }
-        if (unknownNodes != null) {
-            for (UnknownSchemaNodeBuilder unknown : unknownNodes) {
-                leaf.addUnknownSchemaNode(unknown);
-            }
-        }
-    }
-
-    public static void refineContainer(ContainerSchemaNodeBuilder container,
-            RefineHolder refine, int line) {
-        Boolean presence = refine.isPresence();
-        MustDefinition must = refine.getMust();
-        List<UnknownSchemaNodeBuilder> unknownNodes = refine.getUnknownNodes();
-
-        if (presence != null) {
-            container.setPresence(presence);
-        }
-        if (must != null) {
-            container.getConstraints().addMustDefinition(must);
-        }
-        if (unknownNodes != null) {
-            for (UnknownSchemaNodeBuilder unknown : unknownNodes) {
-                container.addUnknownSchemaNode(unknown);
-            }
-        }
-    }
-
-    public static void refineList(ListSchemaNodeBuilder list,
-            RefineHolder refine, int line) {
-        MustDefinition must = refine.getMust();
-        Integer min = refine.getMinElements();
-        Integer max = refine.getMaxElements();
-        List<UnknownSchemaNodeBuilder> unknownNodes = refine.getUnknownNodes();
-
-        if (must != null) {
-            list.getConstraints().addMustDefinition(must);
-        }
-        if (min != null) {
-            list.getConstraints().setMinElements(min);
-        }
-        if (max != null) {
-            list.getConstraints().setMaxElements(max);
-        }
-        if (unknownNodes != null) {
-            for (UnknownSchemaNodeBuilder unknown : unknownNodes) {
-                list.addUnknownSchemaNode(unknown);
-            }
-        }
-    }
-
-    public static void refineLeafList(LeafListSchemaNodeBuilder leafList,
-            RefineHolder refine, int line) {
-        MustDefinition must = refine.getMust();
-        Integer min = refine.getMinElements();
-        Integer max = refine.getMaxElements();
-        List<UnknownSchemaNodeBuilder> unknownNodes = refine.getUnknownNodes();
-
-        if (must != null) {
-            leafList.getConstraints().addMustDefinition(must);
-        }
-        if (min != null) {
-            leafList.getConstraints().setMinElements(min);
-        }
-        if (max != null) {
-            leafList.getConstraints().setMaxElements(max);
-        }
-        if (unknownNodes != null) {
-            for (UnknownSchemaNodeBuilder unknown : unknownNodes) {
-                leafList.addUnknownSchemaNode(unknown);
-            }
-        }
-    }
-
-    public static void refineChoice(ChoiceBuilder choice, RefineHolder refine,
-            int line) {
-        String defaultStr = refine.getDefaultStr();
-        Boolean mandatory = refine.isMandatory();
-        List<UnknownSchemaNodeBuilder> unknownNodes = refine.getUnknownNodes();
-
-        if (defaultStr != null) {
-            choice.setDefaultCase(defaultStr);
-        }
-        if (mandatory != null) {
-            choice.getConstraints().setMandatory(mandatory);
-        }
-        if (unknownNodes != null) {
-            for (UnknownSchemaNodeBuilder unknown : unknownNodes) {
-                choice.addUnknownSchemaNode(unknown);
-            }
-        }
-    }
-
-    public static void refineAnyxml(AnyXmlBuilder anyXml, RefineHolder refine,
-            int line) {
-        Boolean mandatory = refine.isMandatory();
-        MustDefinition must = refine.getMust();
-        List<UnknownSchemaNodeBuilder> unknownNodes = refine.getUnknownNodes();
-
-        if (mandatory != null) {
-            anyXml.getConstraints().setMandatory(mandatory);
-        }
-        if (must != null) {
-            anyXml.getConstraints().addMustDefinition(must);
-        }
-        if (unknownNodes != null) {
-            for (UnknownSchemaNodeBuilder unknown : unknownNodes) {
-                anyXml.addUnknownSchemaNode(unknown);
-            }
-        }
-    }
-
-    public static void checkRefine(SchemaNodeBuilder node, RefineHolder refine) {
-        String name = node.getQName().getLocalName();
-        int line = refine.getLine();
-
-        String defaultStr = refine.getDefaultStr();
-        Boolean mandatory = refine.isMandatory();
-        Boolean presence = refine.isPresence();
-        MustDefinition must = refine.getMust();
-        Integer min = refine.getMinElements();
-        Integer max = refine.getMaxElements();
-
-        if (node instanceof AnyXmlBuilder) {
-            checkRefineDefault(node, defaultStr, line);
-            checkRefinePresence(node, presence, line);
-            checkRefineMinMax(name, line, min, max);
-        } else if (node instanceof ChoiceBuilder) {
-            checkRefinePresence(node, presence, line);
-            checkRefineMust(node, must, line);
-            checkRefineMinMax(name, line, min, max);
-        } else if (node instanceof ContainerSchemaNodeBuilder) {
-            checkRefineDefault(node, defaultStr, line);
-            checkRefineMandatory(node, mandatory, line);
-            checkRefineMust(node, must, line);
-            checkRefineMinMax(name, line, min, max);
-        } else if (node instanceof LeafSchemaNodeBuilder) {
-            checkRefinePresence(node, presence, line);
-            checkRefineMinMax(name, line, min, max);
-        } else if (node instanceof LeafListSchemaNodeBuilder
-                || node instanceof ListSchemaNodeBuilder) {
-            checkRefineDefault(node, defaultStr, line);
-            checkRefinePresence(node, presence, line);
-            checkRefineMandatory(node, mandatory, line);
-        } else if (node instanceof GroupingBuilder
-                || node instanceof TypeDefinitionBuilder
-                || node instanceof UsesNodeBuilder) {
-            checkRefineDefault(node, defaultStr, line);
-            checkRefinePresence(node, presence, line);
-            checkRefineMandatory(node, mandatory, line);
-            checkRefineMust(node, must, line);
-            checkRefineMinMax(name, line, min, max);
-        }
-    }
-
-    private static void checkRefineDefault(SchemaNodeBuilder node,
-            String defaultStr, int line) {
-        if (defaultStr != null) {
-            throw new YangParseException(line, "Can not refine 'default' for '"
-                    + node.getQName().getLocalName() + "'.");
-        }
-    }
-
-    private static void checkRefineMandatory(SchemaNodeBuilder node,
-            Boolean mandatory, int line) {
-        if (mandatory != null) {
-            throw new YangParseException(line,
-                    "Can not refine 'mandatory' for '"
-                            + node.getQName().getLocalName() + "'.");
-        }
-    }
-
-    private static void checkRefinePresence(SchemaNodeBuilder node,
-            Boolean presence, int line) {
-        if (presence != null) {
-            throw new YangParseException(line,
-                    "Can not refine 'presence' for '"
-                            + node.getQName().getLocalName() + "'.");
-        }
-    }
-
-    private static void checkRefineMust(SchemaNodeBuilder node,
-            MustDefinition must, int line) {
-        if (must != null) {
-            throw new YangParseException(line, "Can not refine 'must' for '"
-                    + node.getQName().getLocalName() + "'.");
-        }
-    }
-
-    private static void checkRefineMinMax(String refineTargetName,
-            int refineLine, Integer min, Integer max) {
-        if (min != null || max != null) {
-            throw new YangParseException(refineLine,
-                    "Can not refine 'min-elements' or 'max-elements' for '"
-                            + refineTargetName + "'.");
-        }
-    }
-
-    /**
-     * Perform refine operation of following parameters:
-     * <ul>
-     * <li>description</li>
-     * <li>reference</li>
-     * <li>config</li>
-     * </ul>
-     * 
-     * These parameters may be refined for any node.
-     * 
-     * @param node
-     *            node to refine
-     * @param refine
-     *            refine holder containing values to refine
-     * @param line
-     *            current line in yang model
-     */
-    public static void refineDefault(Builder node, RefineHolder refine, int line) {
-        Class<? extends Builder> cls = node.getClass();
-
-        String description = refine.getDescription();
-        if (description != null) {
-            try {
-                Method method = cls.getDeclaredMethod("setDescription",
-                        String.class);
-                method.invoke(node, description);
-            } catch (Exception e) {
-                throw new YangParseException(line,
-                        "Cannot refine description in " + cls.getName(), e);
-            }
-        }
-
-        String reference = refine.getReference();
-        if (reference != null) {
-            try {
-                Method method = cls.getDeclaredMethod("setReference",
-                        String.class);
-                method.invoke(node, reference);
-            } catch (Exception e) {
-                throw new YangParseException(line,
-                        "Cannot refine reference in " + cls.getName(), e);
-            }
-        }
-
-        Boolean config = refine.isConfig();
-        if (config != null) {
-            try {
-                Method method = cls.getDeclaredMethod("setConfiguration",
-                        Boolean.TYPE);
-                method.invoke(node, config);
-            } catch (Exception e) {
-                throw new YangParseException(line, "Cannot refine config in "
-                        + cls.getName(), e);
-            }
-        }
-    }
-
-    public static LeafSchemaNodeBuilder copyLeafBuilder(
-            final LeafSchemaNodeBuilder old) {
-        final LeafSchemaNodeBuilder copy = new LeafSchemaNodeBuilder(
-                old.getQName(), old.getLine());
+    public static LeafSchemaNodeBuilder copyLeafBuilder(final LeafSchemaNodeBuilder old) {
+        final LeafSchemaNodeBuilder copy = new LeafSchemaNodeBuilder(old.getQName(), old.getLine());
         final TypeDefinition<?> type = old.getType();
-
         if (type == null) {
             copy.setTypedef(old.getTypedef());
         } else {
             copy.setType(type);
         }
-        copy.setPath(old.getPath());
-        copyConstraints(old, copy);
+        copyDataSchemaNodeArgs(old, copy);
+        copyConstraintsFromBuilder(old, copy);
         for (UnknownSchemaNodeBuilder unknown : old.getUnknownNodes()) {
             copy.addUnknownSchemaNode(unknown);
         }
-        copy.setDescription(old.getDescription());
-        copy.setReference(old.getReference());
-        copy.setStatus(old.getStatus());
-        copy.setAugmenting(old.isAugmenting());
-        copy.setConfiguration(old.isConfiguration());
         copy.setDefaultStr(old.getDefaultStr());
         copy.setUnits(old.getUnits());
         return copy;
     }
 
-    public static ContainerSchemaNodeBuilder copyContainerBuilder(
-            final ContainerSchemaNodeBuilder old) {
-        final ContainerSchemaNodeBuilder copy = new ContainerSchemaNodeBuilder(
-                old.getQName(), old.getLine());
-        copy.setPath(old.getPath());
-        copyConstraints(old, copy);
+    public static ContainerSchemaNodeBuilder copyContainerBuilder(final ContainerSchemaNodeBuilder old) {
+        final ContainerSchemaNodeBuilder copy = new ContainerSchemaNodeBuilder(old.getQName(), old.getLine());
+        copyDataSchemaNodeArgs(old, copy);
+        copyConstraintsFromBuilder(old, copy);
         for (UnknownSchemaNodeBuilder unknown : old.getUnknownNodes()) {
             copy.addUnknownSchemaNode(unknown);
         }
@@ -750,21 +724,14 @@ public final class ParserUtils {
         for (UsesNodeBuilder use : old.getUsesNodes()) {
             copy.addUsesNode(use);
         }
-        copy.setDescription(old.getDescription());
-        copy.setReference(old.getReference());
-        copy.setStatus(old.getStatus());
-        copy.setAugmenting(old.isAugmenting());
-        copy.setConfiguration(old.isConfiguration());
         copy.setPresence(old.isPresence());
         return copy;
     }
 
-    public static ListSchemaNodeBuilder copyListBuilder(
-            final ListSchemaNodeBuilder old) {
-        final ListSchemaNodeBuilder copy = new ListSchemaNodeBuilder(
-                old.getQName(), old.getLine());
-        copy.setPath(old.getPath());
-        copyConstraints(old, copy);
+    public static ListSchemaNodeBuilder copyListBuilder(final ListSchemaNodeBuilder old) {
+        final ListSchemaNodeBuilder copy = new ListSchemaNodeBuilder(old.getQName(), old.getLine());
+        copyDataSchemaNodeArgs(old, copy);
+        copyConstraintsFromBuilder(old, copy);
         for (UnknownSchemaNodeBuilder unknown : old.getUnknownNodes()) {
             copy.addUnknownSchemaNode(unknown);
         }
@@ -783,21 +750,14 @@ public final class ParserUtils {
         for (UsesNodeBuilder use : old.getUsesNodes()) {
             copy.addUsesNode(use);
         }
-        copy.setDescription(old.getDescription());
-        copy.setReference(old.getReference());
-        copy.setStatus(old.getStatus());
-        copy.setAugmenting(old.isAugmenting());
-        copy.setConfiguration(old.isConfiguration());
         copy.setUserOrdered(old.isUserOrdered());
         return copy;
     }
 
-    public static LeafListSchemaNodeBuilder copyLeafListBuilder(
-            final LeafListSchemaNodeBuilder old) {
-        final LeafListSchemaNodeBuilder copy = new LeafListSchemaNodeBuilder(
-                old.getQName(), old.getLine());
-        copy.setPath(old.getPath());
-        copyConstraints(old, copy);
+    public static LeafListSchemaNodeBuilder copyLeafListBuilder(final LeafListSchemaNodeBuilder old) {
+        final LeafListSchemaNodeBuilder copy = new LeafListSchemaNodeBuilder(old.getQName(), old.getLine());
+        copyDataSchemaNodeArgs(old, copy);
+        copyConstraintsFromBuilder(old, copy);
         final TypeDefinition<?> type = old.getType();
         if (type == null) {
             copy.setTypedef(old.getTypedef());
@@ -807,20 +767,14 @@ public final class ParserUtils {
         for (UnknownSchemaNodeBuilder unknown : old.getUnknownNodes()) {
             copy.addUnknownSchemaNode(unknown);
         }
-        copy.setDescription(old.getDescription());
-        copy.setReference(old.getReference());
-        copy.setStatus(old.getStatus());
-        copy.setAugmenting(old.isAugmenting());
-        copy.setConfiguration(old.isConfiguration());
         copy.setUserOrdered(old.isUserOrdered());
         return copy;
     }
 
     public static ChoiceBuilder copyChoiceBuilder(final ChoiceBuilder old) {
-        final ChoiceBuilder copy = new ChoiceBuilder(old.getQName(),
-                old.getLine());
-        copy.setPath(old.getPath());
-        copyConstraints(old, copy);
+        final ChoiceBuilder copy = new ChoiceBuilder(old.getQName(), old.getLine());
+        copyDataSchemaNodeArgs(old, copy);
+        copyConstraintsFromBuilder(old, copy);
         for (ChoiceCaseBuilder caseBuilder : old.getCases()) {
             copy.addChildNode(caseBuilder);
         }
@@ -828,32 +782,21 @@ public final class ParserUtils {
             copy.addUnknownSchemaNode(unknown);
         }
         copy.setDefaultCase(old.getDefaultCase());
-        copy.setDescription(old.getDescription());
-        copy.setReference(old.getReference());
-        copy.setStatus(old.getStatus());
-        copy.setAugmenting(old.isAugmenting());
-        copy.setConfiguration(old.isConfiguration());
         return copy;
     }
 
     public static AnyXmlBuilder copyAnyXmlBuilder(final AnyXmlBuilder old) {
-        final AnyXmlBuilder copy = new AnyXmlBuilder(old.getQName(),
-                old.getLine());
-        copy.setPath(old.getPath());
-        copyConstraints(old, copy);
+        final AnyXmlBuilder copy = new AnyXmlBuilder(old.getQName(), old.getLine());
+        copyDataSchemaNodeArgs(old, copy);
+        copyConstraintsFromBuilder(old, copy);
         for (UnknownSchemaNodeBuilder unknown : old.getUnknownNodes()) {
             copy.addUnknownSchemaNode(unknown);
         }
-        copy.setDescription(old.getDescription());
-        copy.setReference(old.getReference());
-        copy.setStatus(old.getStatus());
-        copy.setConfiguration(old.isConfiguration());
         return copy;
     }
 
     public static GroupingBuilder copyGroupingBuilder(final GroupingBuilder old) {
-        final GroupingBuilder copy = new GroupingBuilderImpl(old.getQName(),
-                old.getLine());
+        final GroupingBuilder copy = new GroupingBuilderImpl(old.getQName(), old.getLine());
         copy.setPath(old.getPath());
         for (DataSchemaNodeBuilder child : old.getChildNodes()) {
             copy.addChildNode(child);
@@ -876,10 +819,8 @@ public final class ParserUtils {
         return copy;
     }
 
-    public static TypeDefinitionBuilderImpl copyTypedefBuilder(
-            TypeDefinitionBuilderImpl old) {
-        final TypeDefinitionBuilderImpl copy = new TypeDefinitionBuilderImpl(
-                old.getQName(), old.getLine());
+    public static TypeDefinitionBuilderImpl copyTypedefBuilder(final TypeDefinitionBuilderImpl old) {
+        final TypeDefinitionBuilderImpl copy = new TypeDefinitionBuilderImpl(old.getQName(), old.getLine());
         copy.setPath(old.getPath());
         copy.setDefaultValue(old.getDefaultValue());
         copy.setUnits(old.getUnits());
@@ -905,9 +846,8 @@ public final class ParserUtils {
         return copy;
     }
 
-    public static UsesNodeBuilder copyUsesNodeBuilder(UsesNodeBuilder old) {
-        final UsesNodeBuilder copy = new UsesNodeBuilderImpl(
-                old.getGroupingName(), old.getLine());
+    public static UsesNodeBuilder copyUsesNodeBuilder(final UsesNodeBuilder old) {
+        final UsesNodeBuilder copy = new UsesNodeBuilderImpl(old.getGroupingName(), old.getLine());
         for (AugmentationSchemaBuilder augment : old.getAugmentations()) {
             copy.addAugment(augment);
         }
@@ -918,7 +858,25 @@ public final class ParserUtils {
         return copy;
     }
 
-    private static void copyConstraints(final DataSchemaNodeBuilder oldBuilder,
+    private static void copyDataSchemaNodeArgs(final DataSchemaNodeBuilder oldBuilder,
+            final DataSchemaNodeBuilder newBuilder) {
+        newBuilder.setPath(oldBuilder.getPath());
+        newBuilder.setDescription(oldBuilder.getDescription());
+        newBuilder.setReference(oldBuilder.getReference());
+        newBuilder.setStatus(oldBuilder.getStatus());
+        newBuilder.setAugmenting(oldBuilder.isAugmenting());
+        if (!(oldBuilder instanceof ChoiceCaseNode)) {
+            newBuilder.setConfiguration(oldBuilder.isConfiguration());
+        }
+    }
+
+    /**
+     * Copy constraints from old builder to new builder.
+     *
+     * @param oldBuilder
+     * @param newBuilder
+     */
+    private static void copyConstraintsFromBuilder(final DataSchemaNodeBuilder oldBuilder,
             final DataSchemaNodeBuilder newBuilder) {
         final ConstraintsBuilder oldConstraints = oldBuilder.getConstraints();
         final ConstraintsBuilder newConstraints = newBuilder.getConstraints();
@@ -931,4 +889,528 @@ public final class ParserUtils {
         newConstraints.setMaxElements(oldConstraints.getMaxElements());
     }
 
+    /**
+     * Create LeafSchemaNodeBuilder from given LeafSchemaNode.
+     *
+     * @param leaf
+     *            leaf from which to create builder
+     * @param line
+     *            line in module
+     * @return builder object from leaf
+     */
+    public static LeafSchemaNodeBuilder createLeafBuilder(LeafSchemaNode leaf, int line) {
+        final LeafSchemaNodeBuilder builder = new LeafSchemaNodeBuilder(leaf.getQName(), line);
+        convertDataSchemaNode(leaf, builder);
+        final TypeDefinition<?> type = leaf.getType();
+        builder.setType(type);
+        builder.setPath(leaf.getPath());
+        builder.setUnknownNodes(leaf.getUnknownSchemaNodes());
+        builder.setDefaultStr(leaf.getDefault());
+        builder.setUnits(leaf.getUnits());
+        return builder;
+    }
+
+    public static ContainerSchemaNodeBuilder createContainer(ContainerSchemaNode container, int line) {
+        final ContainerSchemaNodeBuilder builder = new ContainerSchemaNodeBuilder(container.getQName(), line);
+        convertDataSchemaNode(container, builder);
+        builder.setUnknownNodes(container.getUnknownSchemaNodes());
+        builder.setChildNodes(container.getChildNodes());
+        builder.setGroupings(container.getGroupings());
+        builder.setTypedefs(container.getTypeDefinitions());
+        builder.setAugmentations(container.getAvailableAugmentations());
+        builder.setUsesnodes(container.getUses());
+        builder.setPresence(container.isPresenceContainer());
+        return builder;
+    }
+
+    public static ListSchemaNodeBuilder createList(ListSchemaNode list, int line) {
+        ListSchemaNodeBuilder builder = new ListSchemaNodeBuilder(list.getQName(), line);
+        convertDataSchemaNode(list, builder);
+        builder.setUnknownNodes(list.getUnknownSchemaNodes());
+        builder.setTypedefs(list.getTypeDefinitions());
+        builder.setChildNodes(list.getChildNodes());
+        builder.setGroupings(list.getGroupings());
+        builder.setAugmentations(list.getAvailableAugmentations());
+        builder.setUsesnodes(list.getUses());
+        builder.setUserOrdered(builder.isUserOrdered());
+        return builder;
+    }
+
+    public static LeafListSchemaNodeBuilder createLeafList(LeafListSchemaNode leafList, int line) {
+        final LeafListSchemaNodeBuilder builder = new LeafListSchemaNodeBuilder(leafList.getQName(), line);
+        convertDataSchemaNode(leafList, builder);
+        builder.setType(leafList.getType());
+        builder.setUnknownNodes(leafList.getUnknownSchemaNodes());
+        builder.setUserOrdered(leafList.isUserOrdered());
+        return builder;
+    }
+
+    public static ChoiceBuilder createChoice(ChoiceNode choice, int line) {
+        final ChoiceBuilder builder = new ChoiceBuilder(choice.getQName(), line);
+        convertDataSchemaNode(choice, builder);
+        builder.setCases(choice.getCases());
+        builder.setUnknownNodes(choice.getUnknownSchemaNodes());
+        builder.setDefaultCase(choice.getDefaultCase());
+        return builder;
+    }
+
+    public static AnyXmlBuilder createAnyXml(AnyXmlSchemaNode anyxml, int line) {
+        final AnyXmlBuilder builder = new AnyXmlBuilder(anyxml.getQName(), line);
+        convertDataSchemaNode(anyxml, builder);
+        builder.setUnknownNodes(anyxml.getUnknownSchemaNodes());
+        return builder;
+    }
+
+    public static GroupingBuilder createGrouping(GroupingDefinition grouping, int line) {
+        final GroupingBuilderImpl builder = new GroupingBuilderImpl(grouping.getQName(), line);
+        builder.setPath(grouping.getPath());
+        builder.setChildNodes(grouping.getChildNodes());
+        builder.setGroupings(grouping.getGroupings());
+        builder.setTypedefs(grouping.getTypeDefinitions());
+        builder.setUsesnodes(grouping.getUses());
+        builder.setUnknownNodes(grouping.getUnknownSchemaNodes());
+        builder.setDescription(grouping.getDescription());
+        builder.setReference(grouping.getReference());
+        builder.setStatus(grouping.getStatus());
+        return builder;
+    }
+
+    public static TypeDefinitionBuilder createTypedef(ExtendedType typedef, int line) {
+        final TypeDefinitionBuilderImpl builder = new TypeDefinitionBuilderImpl(typedef.getQName(), line);
+        builder.setPath(typedef.getPath());
+        builder.setDefaultValue(typedef.getDefaultValue());
+        builder.setUnits(typedef.getUnits());
+        builder.setDescription(typedef.getDescription());
+        builder.setReference(typedef.getReference());
+        builder.setStatus(typedef.getStatus());
+        builder.setRanges(typedef.getRanges());
+        builder.setLengths(typedef.getLengths());
+        builder.setPatterns(typedef.getPatterns());
+        builder.setFractionDigits(typedef.getFractionDigits());
+        final TypeDefinition<?> type = typedef.getBaseType();
+        builder.setType(type);
+        builder.setUnits(typedef.getUnits());
+        builder.setUnknownNodes(typedef.getUnknownSchemaNodes());
+        return builder;
+    }
+
+    /**
+     * Set DataSchemaNode arguments to builder object
+     *
+     * @param node
+     *            node from which arguments should be read
+     * @param builder
+     *            builder to which arguments should be set
+     */
+    private static void convertDataSchemaNode(DataSchemaNode node, DataSchemaNodeBuilder builder) {
+        builder.setPath(node.getPath());
+        builder.setDescription(node.getDescription());
+        builder.setReference(node.getReference());
+        builder.setStatus(node.getStatus());
+        builder.setAugmenting(node.isAugmenting());
+        if (!(node instanceof ChoiceCaseNode)) {
+            builder.setConfiguration(node.isConfiguration());
+        }
+        copyConstraintsFromDefinition(node.getConstraints(), builder.getConstraints());
+    }
+
+    /**
+     * Copy constraints from constraints definition to constraints builder.
+     *
+     * @param nodeConstraints
+     *            definition from which constraints will be copied
+     * @param constraints
+     *            builder to which constraints will be added
+     */
+    private static void copyConstraintsFromDefinition(final ConstraintDefinition nodeConstraints,
+            final ConstraintsBuilder constraints) {
+        final RevisionAwareXPath when = nodeConstraints.getWhenCondition();
+        final Set<MustDefinition> must = nodeConstraints.getMustConstraints();
+
+        if (when != null) {
+            constraints.addWhenCondition(when.toString());
+        }
+        if (must != null) {
+            for (MustDefinition md : must) {
+                constraints.addMustDefinition(md);
+            }
+        }
+        constraints.setMandatory(nodeConstraints.isMandatory());
+        constraints.setMinElements(nodeConstraints.getMinElements());
+        constraints.setMaxElements(nodeConstraints.getMaxElements());
+    }
+
+    public static void processAugmentationOnContext(final AugmentationSchemaBuilder augmentBuilder,
+            final List<QName> path, final ModuleBuilder module, final String prefix, final int line,
+            final SchemaContext context) {
+        final Module dependentModule = findModuleFromContext(context, module, prefix, line);
+        if (dependentModule == null) {
+            throw new YangParseException(module.getName(), line, "Failed to find referenced module with prefix "
+                    + prefix + ".");
+        }
+        SchemaNode node = dependentModule.getDataChildByName(path.get(0).getLocalName());
+        if (node == null) {
+            Set<NotificationDefinition> notifications = dependentModule.getNotifications();
+            for (NotificationDefinition ntf : notifications) {
+                if (ntf.getQName().getLocalName().equals(path.get(0).getLocalName())) {
+                    node = ntf;
+                    break;
+                }
+            }
+        }
+        if (node == null) {
+            return;
+        }
+
+        for (int i = 1; i < path.size(); i++) {
+            if (node instanceof DataNodeContainer) {
+                DataNodeContainer ref = (DataNodeContainer) node;
+                node = ref.getDataChildByName(path.get(i).getLocalName());
+            }
+        }
+        if (node == null) {
+            return;
+        }
+
+        if (node instanceof ContainerSchemaNodeImpl) {
+            // includes container, input and output statement
+            ContainerSchemaNodeImpl c = (ContainerSchemaNodeImpl) node;
+            ContainerSchemaNodeBuilder cb = c.toBuilder();
+            fillAugmentTarget(augmentBuilder, cb);
+            ((AugmentationTargetBuilder) cb).addAugmentation(augmentBuilder);
+            SchemaPath oldPath = cb.getPath();
+            cb.rebuild();
+            augmentBuilder.setTargetPath(new SchemaPath(oldPath.getPath(), oldPath.isAbsolute()));
+            augmentBuilder.setResolved(true);
+            module.augmentResolved();
+        } else if (node instanceof ListSchemaNodeImpl) {
+            ListSchemaNodeImpl l = (ListSchemaNodeImpl) node;
+            ListSchemaNodeBuilder lb = l.toBuilder();
+            fillAugmentTarget(augmentBuilder, lb);
+            ((AugmentationTargetBuilder) lb).addAugmentation(augmentBuilder);
+            SchemaPath oldPath = lb.getPath();
+            lb.rebuild();
+            augmentBuilder.setTargetPath(new SchemaPath(oldPath.getPath(), oldPath.isAbsolute()));
+            augmentBuilder.setResolved(true);
+            module.augmentResolved();
+        } else if (node instanceof ChoiceNodeImpl) {
+            ChoiceNodeImpl ch = (ChoiceNodeImpl) node;
+            ChoiceBuilder chb = ch.toBuilder();
+            fillAugmentTarget(augmentBuilder, chb);
+            ((AugmentationTargetBuilder) chb).addAugmentation(augmentBuilder);
+            SchemaPath oldPath = chb.getPath();
+            chb.rebuild();
+            augmentBuilder.setTargetPath(new SchemaPath(oldPath.getPath(), oldPath.isAbsolute()));
+            augmentBuilder.setResolved(true);
+            module.augmentResolved();
+        } else if (node instanceof ChoiceCaseNodeImpl) {
+            ChoiceCaseNodeImpl chc = (ChoiceCaseNodeImpl) node;
+            ChoiceCaseBuilder chcb = chc.toBuilder();
+            fillAugmentTarget(augmentBuilder, chcb);
+            ((AugmentationTargetBuilder) chcb).addAugmentation(augmentBuilder);
+            SchemaPath oldPath = chcb.getPath();
+            chcb.rebuild();
+            augmentBuilder.setTargetPath(new SchemaPath(oldPath.getPath(), oldPath.isAbsolute()));
+            augmentBuilder.setResolved(true);
+            module.augmentResolved();
+        } else if (node instanceof NotificationDefinitionImpl) {
+            NotificationDefinitionImpl nd = (NotificationDefinitionImpl) node;
+            NotificationBuilder nb = nd.toBuilder();
+            fillAugmentTarget(augmentBuilder, nb);
+            ((AugmentationTargetBuilder) nb).addAugmentation(augmentBuilder);
+            SchemaPath oldPath = nb.getPath();
+            nb.rebuild();
+            augmentBuilder.setTargetPath(new SchemaPath(oldPath.getPath(), oldPath.isAbsolute()));
+            augmentBuilder.setResolved(true);
+            module.augmentResolved();
+        } else {
+            throw new YangParseException(module.getName(), line, "Target of type " + node.getClass()
+                    + " can not be augmented.");
+        }
+    }
+
+    public static void processAugmentation(final AugmentationSchemaBuilder augmentBuilder, final List<QName> path,
+            final ModuleBuilder module, final QName qname, final ModuleBuilder dependentModuleBuilder) {
+        DataSchemaNodeBuilder currentParent = null;
+        for (DataSchemaNodeBuilder child : dependentModuleBuilder.getChildNodes()) {
+            final QName childQName = child.getQName();
+            if (childQName.getLocalName().equals(qname.getLocalName())) {
+                currentParent = child;
+                break;
+            }
+        }
+
+        if (currentParent == null) {
+            return;
+        }
+
+        for (int i = 1; i < path.size(); i++) {
+            final QName currentQName = path.get(i);
+            DataSchemaNodeBuilder newParent = null;
+            for (DataSchemaNodeBuilder child : ((DataNodeContainerBuilder) currentParent).getChildNodes()) {
+                final QName childQName = child.getQName();
+                if (childQName.getLocalName().equals(currentQName.getLocalName())) {
+                    newParent = child;
+                    break;
+                }
+            }
+            if (newParent == null) {
+                break; // node not found, quit search
+            } else {
+                currentParent = newParent;
+            }
+        }
+
+        final String currentName = currentParent.getQName().getLocalName();
+        final String lastAugmentPathElementName = path.get(path.size() - 1).getLocalName();
+        if (currentName.equals(lastAugmentPathElementName)) {
+
+            if (currentParent instanceof ChoiceBuilder) {
+                fillAugmentTarget(augmentBuilder, (ChoiceBuilder) currentParent);
+            } else {
+                fillAugmentTarget(augmentBuilder, (DataNodeContainerBuilder) currentParent);
+            }
+            ((AugmentationTargetBuilder) currentParent).addAugmentation(augmentBuilder);
+            SchemaPath oldPath = currentParent.getPath();
+            augmentBuilder.setTargetPath(new SchemaPath(oldPath.getPath(), oldPath.isAbsolute()));
+            augmentBuilder.setResolved(true);
+            module.augmentResolved();
+        }
+    }
+
+    /**
+     * Create new type builder based on old type with new base type.
+     *
+     * @param newBaseType
+     *            new base type builder
+     * @param oldExtendedType
+     *            old type
+     * @param modules
+     *            all loaded modules
+     * @param module
+     *            current module
+     * @param line
+     *            current line in module
+     * @return new type builder based on old type with new base type
+     */
+    public static TypeDefinitionBuilder extendedTypeWithNewBaseTypeBuilder(final TypeDefinitionBuilder newBaseType,
+            final ExtendedType oldExtendedType, final Map<String, TreeMap<Date, ModuleBuilder>> modules,
+            final ModuleBuilder module, final int line) {
+        final TypeConstraints tc = new TypeConstraints(module.getName(), line);
+        tc.addFractionDigits(oldExtendedType.getFractionDigits());
+        tc.addLengths(oldExtendedType.getLengths());
+        tc.addPatterns(oldExtendedType.getPatterns());
+        tc.addRanges(oldExtendedType.getRanges());
+
+        final TypeConstraints constraints = findConstraintsFromTypeBuilder(newBaseType, tc, modules, module, null);
+        final TypeDefinitionBuilderImpl newType = new TypeDefinitionBuilderImpl(oldExtendedType.getQName(), line);
+        newType.setTypedef(newBaseType);
+        newType.setPath(oldExtendedType.getPath());
+        newType.setDescription(oldExtendedType.getDescription());
+        newType.setReference(oldExtendedType.getReference());
+        newType.setStatus(oldExtendedType.getStatus());
+        newType.setLengths(constraints.getLength());
+        newType.setPatterns(constraints.getPatterns());
+        newType.setRanges(constraints.getRange());
+        newType.setFractionDigits(constraints.getFractionDigits());
+        newType.setUnits(oldExtendedType.getUnits());
+        newType.setDefaultValue(oldExtendedType.getDefaultValue());
+        newType.setUnknownNodes(oldExtendedType.getUnknownSchemaNodes());
+        return newType;
+    }
+
+    /**
+     * Create new type builder based on old type with new base type.
+     *
+     * @param newBaseType
+     *            new base type
+     * @param oldExtendedType
+     *            old type
+     * @param modules
+     *            all loaded modules
+     * @param module
+     *            current module
+     * @param line
+     *            current line in module
+     * @return new type builder based on old type with new base type
+     */
+    public static TypeDefinitionBuilder extendedTypeWithNewBaseType(final TypeDefinition<?> newBaseType,
+            final ExtendedType oldExtendedType, final ModuleBuilder module, final int line) {
+        final TypeConstraints tc = new TypeConstraints(module.getName(), line);
+
+        final TypeConstraints constraints = findConstraintsFromTypeDefinition(newBaseType, tc);
+        final TypeDefinitionBuilderImpl newType = new TypeDefinitionBuilderImpl(oldExtendedType.getQName(), line);
+        newType.setType(newBaseType);
+        newType.setPath(oldExtendedType.getPath());
+        newType.setDescription(oldExtendedType.getDescription());
+        newType.setReference(oldExtendedType.getReference());
+        newType.setStatus(oldExtendedType.getStatus());
+        newType.setLengths(constraints.getLength());
+        newType.setPatterns(constraints.getPatterns());
+        newType.setRanges(constraints.getRange());
+        newType.setFractionDigits(constraints.getFractionDigits());
+        newType.setUnits(oldExtendedType.getUnits());
+        newType.setDefaultValue(oldExtendedType.getDefaultValue());
+        newType.setUnknownNodes(oldExtendedType.getUnknownSchemaNodes());
+        return newType;
+    }
+
+    /**
+     * Pull restrictions from type and add them to constraints.
+     *
+     * @param typeToResolve
+     *            type from which constraints will be read
+     * @param constraints
+     *            constraints object to which constraints will be added
+     * @return constraints contstraints object containing constraints from given
+     *         type
+     */
+    private static TypeConstraints findConstraintsFromTypeDefinition(final TypeDefinition<?> typeToResolve,
+            final TypeConstraints constraints) {
+        // union type cannot be restricted
+        if (typeToResolve instanceof UnionTypeDefinition) {
+            return constraints;
+        }
+        if (typeToResolve instanceof ExtendedType) {
+            ExtendedType extType = (ExtendedType) typeToResolve;
+            constraints.addFractionDigits(extType.getFractionDigits());
+            constraints.addLengths(extType.getLengths());
+            constraints.addPatterns(extType.getPatterns());
+            constraints.addRanges(extType.getRanges());
+            return findConstraintsFromTypeDefinition(extType.getBaseType(), constraints);
+        } else {
+            mergeConstraints(typeToResolve, constraints);
+            return constraints;
+        }
+    }
+
+    public static TypeConstraints findConstraintsFromTypeBuilder(final TypeAwareBuilder nodeToResolve,
+            final TypeConstraints constraints, final Map<String, TreeMap<Date, ModuleBuilder>> modules,
+            final ModuleBuilder builder, final SchemaContext context) {
+
+        // union type cannot be restricted
+        if (nodeToResolve instanceof UnionTypeBuilder) {
+            return constraints;
+        }
+
+        if (nodeToResolve instanceof TypeDefinitionBuilder) {
+            TypeDefinitionBuilder typedefToResolve = (TypeDefinitionBuilder) nodeToResolve;
+            constraints.addFractionDigits(typedefToResolve.getFractionDigits());
+            constraints.addLengths(typedefToResolve.getLengths());
+            constraints.addPatterns(typedefToResolve.getPatterns());
+            constraints.addRanges(typedefToResolve.getRanges());
+        }
+
+        TypeDefinition<?> type = nodeToResolve.getType();
+        if (type == null) {
+            return findConstraintsFromTypeBuilder(nodeToResolve.getTypedef(), constraints, modules, builder, context);
+        } else {
+            QName qname = type.getQName();
+            if (type instanceof UnknownType) {
+                ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, builder, qname.getPrefix(),
+                        nodeToResolve.getLine());
+                if (dependentModuleBuilder == null) {
+                    if (context == null) {
+                        throw new YangParseException(builder.getName(), nodeToResolve.getLine(),
+                                "Failed to resolved type constraints.");
+                    }
+                    Module dm = findModuleFromContext(context, builder, qname.getPrefix(), nodeToResolve.getLine());
+                    TypeDefinition<?> t = findTypeByName(dm.getTypeDefinitions(), qname.getLocalName());
+                    if (t instanceof ExtendedType) {
+                        ExtendedType extType = (ExtendedType) t;
+                        constraints.addFractionDigits(extType.getFractionDigits());
+                        constraints.addLengths(extType.getLengths());
+                        constraints.addPatterns(extType.getPatterns());
+                        constraints.addRanges(extType.getRanges());
+                        return constraints;
+                    } else {
+                        mergeConstraints(t, constraints);
+                        return constraints;
+                    }
+                } else {
+                    TypeDefinitionBuilder tdb = findTypeDefinitionBuilder(nodeToResolve.getPath(),
+                            dependentModuleBuilder, qname.getLocalName(), builder.getName(), nodeToResolve.getLine());
+                    return findConstraintsFromTypeBuilder(tdb, constraints, modules, dependentModuleBuilder, context);
+                }
+            } else if (type instanceof ExtendedType) {
+                ExtendedType extType = (ExtendedType) type;
+                constraints.addFractionDigits(extType.getFractionDigits());
+                constraints.addLengths(extType.getLengths());
+                constraints.addPatterns(extType.getPatterns());
+                constraints.addRanges(extType.getRanges());
+
+                TypeDefinition<?> base = extType.getBaseType();
+                if (base instanceof UnknownType) {
+                    ModuleBuilder dependentModule = findDependentModuleBuilder(modules, builder, base.getQName()
+                            .getPrefix(), nodeToResolve.getLine());
+                    TypeDefinitionBuilder tdb = findTypeDefinitionBuilder(nodeToResolve.getPath(), dependentModule,
+                            base.getQName().getLocalName(), builder.getName(), nodeToResolve.getLine());
+                    return findConstraintsFromTypeBuilder(tdb, constraints, modules, dependentModule, context);
+                } else {
+                    // it has to be base yang type
+                    mergeConstraints(type, constraints);
+                    return constraints;
+                }
+            } else {
+                // it is base yang type
+                mergeConstraints(type, constraints);
+                return constraints;
+            }
+        }
+    }
+
+    /**
+     * Search for type definition builder by name.
+     *
+     * @param dirtyNodeSchemaPath
+     *            schema path of node which contains unresolved type
+     * @param dependentModule
+     *            module which should contains referenced type
+     * @param typeName
+     *            name of type definition
+     * @param currentModuleName
+     *            name of current module
+     * @param line
+     *            current line in yang model
+     * @return
+     */
+    public static TypeDefinitionBuilder findTypeDefinitionBuilder(final SchemaPath dirtyNodeSchemaPath,
+            final ModuleBuilder dependentModule, final String typeName, final String currentModuleName, final int line) {
+        final List<QName> path = dirtyNodeSchemaPath.getPath();
+        TypeDefinitionBuilder result = null;
+
+        Set<TypeDefinitionBuilder> typedefs = dependentModule.getModuleTypedefs();
+        result = findTypedefBuilderByName(typedefs, typeName);
+
+        if (result == null) {
+            Builder currentNode = null;
+            final List<String> currentPath = new ArrayList<String>();
+            currentPath.add(dependentModule.getName());
+
+            for (int i = 0; i < path.size(); i++) {
+                QName qname = path.get(i);
+                currentPath.add(qname.getLocalName());
+                currentNode = dependentModule.getModuleNode(currentPath);
+
+                if (currentNode instanceof RpcDefinitionBuilder) {
+                    typedefs = ((RpcDefinitionBuilder) currentNode).getTypeDefinitions();
+                } else if (currentNode instanceof DataNodeContainerBuilder) {
+                    typedefs = ((DataNodeContainerBuilder) currentNode).getTypeDefinitions();
+                } else {
+                    typedefs = Collections.emptySet();
+                }
+
+                result = findTypedefBuilderByName(typedefs, typeName);
+                if (result != null) {
+                    break;
+                }
+            }
+        }
+
+        if (result != null) {
+            return result;
+        }
+        throw new YangParseException(currentModuleName, line, "Referenced type '" + typeName + "' not found.");
+    }
+
 }