Yang-maven-plugin refactored + fixed bugs.
[controller.git] / opendaylight / sal / yang-prototype / code-generator / yang-model-parser-impl / src / main / java / org / opendaylight / controller / yang / parser / impl / YangParserImpl.java
index 41392b0f49fc80195f0064ac349b2ecb94cc81ee..25af3ebae5f47f9cb875b7a91af8de512c217bf3 100644 (file)
@@ -12,7 +12,6 @@ import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
-import java.net.URI;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Date;
@@ -20,9 +19,9 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.NoSuchElementException;
 import java.util.Set;
 import java.util.TreeMap;
@@ -34,13 +33,8 @@ import org.antlr.v4.runtime.tree.ParseTreeWalker;
 import org.opendaylight.controller.antlrv4.code.gen.YangLexer;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser;
 import org.opendaylight.controller.yang.common.QName;
-import org.opendaylight.controller.yang.model.api.DataSchemaNode;
-import org.opendaylight.controller.yang.model.api.ExtensionDefinition;
 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.RpcDefinition;
 import org.opendaylight.controller.yang.model.api.SchemaContext;
 import org.opendaylight.controller.yang.model.api.SchemaPath;
 import org.opendaylight.controller.yang.model.api.TypeDefinition;
@@ -58,9 +52,10 @@ 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.ChildNodeBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.DataNodeContainerBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.DataSchemaNodeBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.GroupingBuilder;
+import org.opendaylight.controller.yang.parser.builder.api.SchemaNodeBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.TypeAwareBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.UsesNodeBuilder;
@@ -73,7 +68,8 @@ import org.opendaylight.controller.yang.parser.builder.impl.LeafListSchemaNodeBu
 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.ModuleBuilder;
-import org.opendaylight.controller.yang.parser.builder.impl.TypedefBuilder;
+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.util.ModuleDependencySort;
@@ -85,35 +81,80 @@ import org.opendaylight.controller.yang.validator.YangModelBasicValidator;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class YangParserImpl implements YangModelParser {
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
+public final class YangParserImpl implements YangModelParser {
 
     private static final Logger logger = LoggerFactory
             .getLogger(YangParserImpl.class);
 
     @Override
-    public Set<Module> parseYangModels(final List<File> yangFiles) {
+    public Map<File, Module> parseYangModelsMapped(List<File> yangFiles) {
         if (yangFiles != null) {
-            final List<InputStream> inputStreams = new ArrayList<InputStream>();
+            final Map<InputStream, File> inputStreams = Maps.newHashMap();
 
             for (final File yangFile : yangFiles) {
                 try {
-                    inputStreams.add(new FileInputStream(yangFile));
+                    inputStreams.put(new FileInputStream(yangFile), yangFile);
                 } catch (FileNotFoundException e) {
                     logger.warn("Exception while reading yang file: "
                             + yangFile.getName(), e);
                 }
             }
-            final Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModuleBuilders(inputStreams);
-            return build(modules);
+
+            Map<ModuleBuilder, InputStream> builderToStreamMap = Maps
+                    .newHashMap();
+
+            final Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModuleBuilders(
+                    Lists.newArrayList(inputStreams.keySet()),
+                    builderToStreamMap);
+            // return new LinkedHashSet<Module>(build(modules).values());
+
+            Map<File, Module> retVal = Maps.newLinkedHashMap();
+            Map<ModuleBuilder, Module> builderToModuleMap = build(modules);
+
+            for (Entry<ModuleBuilder, Module> builderToModule : builderToModuleMap
+                    .entrySet()) {
+                retVal.put(inputStreams.get(builderToStreamMap
+                        .get(builderToModule.getKey())), builderToModule
+                        .getValue());
+            }
+
+            return retVal;
         }
-        return Collections.emptySet();
+        return Collections.emptyMap();
+    }
+
+    @Override
+    public Set<Module> parseYangModels(final List<File> yangFiles) {
+        return Sets.newLinkedHashSet(parseYangModelsMapped(yangFiles).values());
     }
 
     @Override
     public Set<Module> parseYangModelsFromStreams(
             final List<InputStream> yangModelStreams) {
-        final Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModuleBuilders(yangModelStreams);
-        return build(modules);
+        return Sets.newHashSet(parseYangModelsFromStreamsMapped(
+                yangModelStreams).values());
+    }
+
+    @Override
+    public Map<InputStream, Module> parseYangModelsFromStreamsMapped(
+            final List<InputStream> yangModelStreams) {
+        Map<ModuleBuilder, InputStream> builderToStreamMap = Maps.newHashMap();
+
+        final Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModuleBuilders(
+                yangModelStreams, builderToStreamMap);
+        Map<InputStream, Module> retVal = Maps.newLinkedHashMap();
+        Map<ModuleBuilder, Module> builderToModuleMap = build(modules);
+
+        for (Entry<ModuleBuilder, Module> builderToModule : builderToModuleMap
+                .entrySet()) {
+            retVal.put(builderToStreamMap.get(builderToModule.getKey()),
+                    builderToModule.getValue());
+        }
+        return retVal;
     }
 
     @Override
@@ -121,12 +162,11 @@ public class YangParserImpl implements YangModelParser {
         return new SchemaContextImpl(modules);
     }
 
-    private Map<String, TreeMap<Date, ModuleBuilder>> resolveModuleBuilders(
-            final List<InputStream> yangFileStreams) {
-        //Linked Hash Map MUST be used because Linked Hash Map preserves ORDER of items stored in map.
-        final Map<String, TreeMap<Date, ModuleBuilder>> modules = new LinkedHashMap<String, TreeMap<Date, ModuleBuilder>>();
+    private ModuleBuilder[] parseModuleBuilders(List<InputStream> inputStreams,
+            Map<ModuleBuilder, InputStream> streamToBuilderMap) {
+
         final ParseTreeWalker walker = new ParseTreeWalker();
-        final List<ParseTree> trees = parseStreams(yangFileStreams);
+        final List<ParseTree> trees = parseStreams(inputStreams);
         final ModuleBuilder[] builders = new ModuleBuilder[trees.size()];
 
         // validate yang
@@ -136,12 +176,29 @@ public class YangParserImpl implements YangModelParser {
         for (int i = 0; i < trees.size(); i++) {
             yangModelParser = new YangParserListenerImpl();
             walker.walk(yangModelParser, trees.get(i));
-            builders[i] = yangModelParser.getModuleBuilder();
+            ModuleBuilder moduleBuilder = yangModelParser.getModuleBuilder();
+
+            // We expect the order of trees and streams has to be the same
+            streamToBuilderMap.put(moduleBuilder, inputStreams.get(i));
+            builders[i] = moduleBuilder;
         }
+        return builders;
+    }
+
+    private Map<String, TreeMap<Date, ModuleBuilder>> resolveModuleBuilders(
+            final List<InputStream> yangFileStreams,
+            Map<ModuleBuilder, InputStream> streamToBuilderMap) {
+
+        final ModuleBuilder[] builders = parseModuleBuilders(yangFileStreams,
+                streamToBuilderMap);
+
+        // Linked Hash Map MUST be used because Linked Hash Map preserves ORDER
+        // of items stored in map.
+        final LinkedHashMap<String, TreeMap<Date, ModuleBuilder>> modules = new LinkedHashMap<String, TreeMap<Date, ModuleBuilder>>();
 
         // module dependency graph sorted
         List<ModuleBuilder> sorted = ModuleDependencySort.sort(builders);
-        
+
         for (ModuleBuilder builder : sorted) {
             final String builderName = builder.getName();
             Date builderRevision = builder.getRevision();
@@ -181,7 +238,7 @@ public class YangParserImpl implements YangModelParser {
         return result;
     }
 
-    private Set<Module> build(
+    private Map<ModuleBuilder, Module> build(
             final Map<String, TreeMap<Date, ModuleBuilder>> modules) {
         // fix unresolved nodes
         for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules
@@ -195,9 +252,10 @@ public class YangParserImpl implements YangModelParser {
         resolveAugments(modules);
 
         // build
-        // Linked Hash Set MUST be used otherwise the Set will not maintain order!
-        // http://docs.oracle.com/javase/6/docs/api/java/util/LinkedHashSet.html
-        final Set<Module> result = new LinkedHashSet<Module>();
+        // LinkedHashMap MUST be used otherwise the values will not maintain
+        // order!
+        // http://docs.oracle.com/javase/6/docs/api/java/util/LinkedHashMap.html
+        final Map<ModuleBuilder, Module> result = new LinkedHashMap<ModuleBuilder, Module>();
         for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules
                 .entrySet()) {
             final Map<Date, Module> modulesByRevision = new HashMap<Date, Module>();
@@ -206,7 +264,7 @@ public class YangParserImpl implements YangModelParser {
                 final ModuleBuilder moduleBuilder = childEntry.getValue();
                 final Module module = moduleBuilder.build();
                 modulesByRevision.put(childEntry.getKey(), module);
-                result.add(module);
+                result.put(moduleBuilder, module);
             }
         }
         return result;
@@ -217,14 +275,14 @@ public class YangParserImpl implements YangModelParser {
             final ModuleBuilder builder) {
         resolveDirtyNodes(modules, builder);
         resolveIdentities(modules, builder);
-        resolveUses(modules, builder);
+        resolveUsesRefines(modules, builder);
         resolveUnknownNodes(modules, builder);
     }
 
     /**
      * Search for dirty nodes (node which contains UnknownType) and resolve
      * unknown types.
-     * 
+     *
      * @param modules
      *            all available modules
      * @param module
@@ -250,12 +308,13 @@ public class YangParserImpl implements YangModelParser {
                             final UnknownType unknownType = (UnknownType) td;
                             final TypeDefinitionBuilder resolvedType = resolveTypeUnion(
                                     nodeToResolve, unknownType, modules, module);
-                            union.setType(resolvedType);
+                            union.setTypedef(resolvedType);
                             toRemove.add(unknownType);
                         }
                     }
                     unionTypes.removeAll(toRemove);
                 } else if (nodeToResolve.getTypedef() instanceof IdentityrefTypeBuilder) {
+                    // different handling for identityref types
                     IdentityrefTypeBuilder idref = (IdentityrefTypeBuilder) nodeToResolve
                             .getTypedef();
                     nodeToResolve.setType(new IdentityrefType(findFullQName(
@@ -263,28 +322,28 @@ public class YangParserImpl implements YangModelParser {
                 } else {
                     final TypeDefinitionBuilder resolvedType = resolveType(
                             nodeToResolve, modules, module);
-                    nodeToResolve.setType(resolvedType);
+                    nodeToResolve.setTypedef(resolvedType);
                 }
             }
         }
     }
 
     private TypeDefinitionBuilder resolveType(
-            final TypeAwareBuilder typeToResolve,
+            final TypeAwareBuilder nodeToResolve,
             final Map<String, TreeMap<Date, ModuleBuilder>> modules,
             final ModuleBuilder builder) {
         final TypeConstraints constraints = new TypeConstraints();
 
-        final TypeDefinitionBuilder targetType = getTypedefBuilder(
-                typeToResolve, modules, builder);
-        final TypeConstraints tConstraints = findConstraints(typeToResolve,
+        final TypeDefinitionBuilder targetTypeBuilder = getTypeDefinitionBuilderFromDirtyNode(
+                nodeToResolve, modules, builder);
+        final TypeConstraints tConstraints = findConstraints(nodeToResolve,
                 constraints, modules, builder);
-        targetType.setRanges(tConstraints.getRange());
-        targetType.setLengths(tConstraints.getLength());
-        targetType.setPatterns(tConstraints.getPatterns());
-        targetType.setFractionDigits(tConstraints.getFractionDigits());
+        targetTypeBuilder.setRanges(tConstraints.getRange());
+        targetTypeBuilder.setLengths(tConstraints.getLength());
+        targetTypeBuilder.setPatterns(tConstraints.getPatterns());
+        targetTypeBuilder.setFractionDigits(tConstraints.getFractionDigits());
 
-        return targetType;
+        return targetTypeBuilder;
     }
 
     private TypeDefinitionBuilder resolveTypeUnion(
@@ -294,38 +353,34 @@ public class YangParserImpl implements YangModelParser {
             final ModuleBuilder builder) {
         final TypeConstraints constraints = new TypeConstraints();
 
-        final TypeDefinitionBuilder targetType = getUnionBuilder(typeToResolve,
-                unknownType, modules, builder);
+        final TypeDefinitionBuilder targetTypeBuilder = getUnionBuilder(
+                typeToResolve, unknownType, modules, builder);
         final TypeConstraints tConstraints = findConstraints(typeToResolve,
                 constraints, modules, builder);
-        targetType.setRanges(tConstraints.getRange());
-        targetType.setLengths(tConstraints.getLength());
-        targetType.setPatterns(tConstraints.getPatterns());
-        targetType.setFractionDigits(tConstraints.getFractionDigits());
+        targetTypeBuilder.setRanges(tConstraints.getRange());
+        targetTypeBuilder.setLengths(tConstraints.getLength());
+        targetTypeBuilder.setPatterns(tConstraints.getPatterns());
+        targetTypeBuilder.setFractionDigits(tConstraints.getFractionDigits());
 
-        return targetType;
+        return targetTypeBuilder;
     }
 
-    private TypeDefinitionBuilder getTypedefBuilder(
+    private TypeDefinitionBuilder getTypeDefinitionBuilderFromDirtyNode(
             final TypeAwareBuilder nodeToResolve,
             final Map<String, TreeMap<Date, ModuleBuilder>> modules,
-            final ModuleBuilder builder) {
-
-        final TypeDefinition<?> nodeToResolveBase = nodeToResolve.getType();
-        if (nodeToResolveBase != null
-                && !(nodeToResolveBase instanceof UnknownType)) {
-            return (TypeDefinitionBuilder) nodeToResolve;
-        }
+            final ModuleBuilder module) {
 
         final UnknownType unknownType = (UnknownType) nodeToResolve.getType();
         final QName unknownTypeQName = unknownType.getQName();
 
         // search for module which contains referenced typedef
         final ModuleBuilder dependentModule = findDependentModule(modules,
-                builder, unknownTypeQName.getPrefix(), nodeToResolve.getLine());
-        final TypeDefinitionBuilder lookedUpBuilder = findTypedefBuilderByName(
-                dependentModule, unknownTypeQName.getLocalName(),
-                builder.getName(), nodeToResolve.getLine());
+                module, unknownTypeQName.getPrefix(), nodeToResolve.getLine());
+
+        final TypeDefinitionBuilder lookedUpBuilder = findTypeDefinitionBuilder(
+                nodeToResolve.getPath(), dependentModule,
+                unknownTypeQName.getLocalName(), module.getName(),
+                nodeToResolve.getLine());
 
         final TypeDefinitionBuilder lookedUpBuilderCopy = copyTypedefBuilder(
                 lookedUpBuilder, nodeToResolve instanceof TypeDefinitionBuilder);
@@ -350,9 +405,10 @@ public class YangParserImpl implements YangModelParser {
         // search for module which contains referenced typedef
         final ModuleBuilder dependentModule = findDependentModule(modules,
                 module, unknownTypeQName.getPrefix(), nodeToResolve.getLine());
-        final TypeDefinitionBuilder lookedUpBuilder = findTypedefBuilderByName(
-                dependentModule, unknownTypeQName.getLocalName(),
-                module.getName(), nodeToResolve.getLine());
+        final TypeDefinitionBuilder lookedUpBuilder = findTypeDefinitionBuilder(
+                nodeToResolve.getPath(), dependentModule,
+                unknownTypeQName.getLocalName(), module.getName(),
+                nodeToResolve.getLine());
 
         final TypeDefinitionBuilder lookedUpBuilderCopy = copyTypedefBuilder(
                 lookedUpBuilder, nodeToResolve instanceof TypeDefinitionBuilder);
@@ -366,14 +422,14 @@ public class YangParserImpl implements YangModelParser {
         if (old instanceof UnionTypeBuilder) {
             final UnionTypeBuilder oldUnion = (UnionTypeBuilder) old;
             final UnionTypeBuilder newUnion = new UnionTypeBuilder(
-                    oldUnion.getActualPath(), oldUnion.getNamespace(),
-                    oldUnion.getRevision(), old.getLine());
+                    old.getLine());
             for (TypeDefinition<?> td : oldUnion.getTypes()) {
                 newUnion.setType(td);
             }
             for (TypeDefinitionBuilder tdb : oldUnion.getTypedefs()) {
-                newUnion.setType(copyTypedefBuilder(tdb, true));
+                newUnion.setTypedef(copyTypedefBuilder(tdb, true));
             }
+            newUnion.setPath(old.getPath());
             return newUnion;
         }
 
@@ -381,8 +437,8 @@ public class YangParserImpl implements YangModelParser {
         final QName newName = new QName(oldName.getNamespace(),
                 oldName.getRevision(), oldName.getPrefix(),
                 oldName.getLocalName());
-        final TypeDefinitionBuilder tdb = new TypedefBuilder(newName,
-                old.getLine());
+        final TypeDefinitionBuilder tdb = new TypeDefinitionBuilderImpl(
+                newName, old.getLine());
 
         tdb.setRanges(old.getRanges());
         tdb.setLengths(old.getLengths());
@@ -392,7 +448,7 @@ public class YangParserImpl implements YangModelParser {
 
         final TypeDefinition<?> oldType = old.getType();
         if (oldType == null) {
-            tdb.setType(old.getTypedef());
+            tdb.setTypedef(old.getTypedef());
         } else {
             tdb.setType(oldType);
         }
@@ -421,7 +477,7 @@ public class YangParserImpl implements YangModelParser {
                     final UnknownType unknownType = (UnknownType) td;
                     final TypeDefinitionBuilder resolvedType = resolveTypeUnion(
                             union, unknownType, modules, builder);
-                    union.setType(resolvedType);
+                    union.setTypedef(resolvedType);
                     toRemove.add(unknownType);
                 }
             }
@@ -440,9 +496,9 @@ public class YangParserImpl implements YangModelParser {
             final String unknownTypePrefix = unknownTypeQName.getPrefix();
             final ModuleBuilder dependentModule = findDependentModule(modules,
                     builder, unknownTypePrefix, copy.getLine());
-            final TypeDefinitionBuilder utBuilder = getTypedefBuilder(copy,
-                    modules, dependentModule);
-            copy.setType(utBuilder);
+            final TypeDefinitionBuilder utBuilder = getTypeDefinitionBuilderFromDirtyNode(
+                    copy, modules, dependentModule);
+            copy.setTypedef(utBuilder);
             return copy;
         } else if (base == null && baseTdb != null) {
             // make a copy of baseTypeDef and call again
@@ -450,27 +506,14 @@ public class YangParserImpl implements YangModelParser {
                     baseTdb, true);
             final TypeDefinitionBuilder baseTdbCopyResolved = resolveCopiedBuilder(
                     baseTdbCopy, modules, builder);
-            copy.setType(baseTdbCopyResolved);
+            copy.setTypedef(baseTdbCopyResolved);
             return copy;
         } else {
-            throw new IllegalStateException("Failed to resolve type "
-                    + copy.getQName().getLocalName());
+            throw new YangParseException(copy.getLine(),
+                    "Failed to resolve type " + copy.getQName().getLocalName());
         }
     }
 
-    private TypeDefinitionBuilder findTypedefBuilder(
-            final QName unknownTypeQName,
-            final Map<String, TreeMap<Date, ModuleBuilder>> modules,
-            final ModuleBuilder builder, int line) {
-        // search for module which contains referenced typedef
-        final ModuleBuilder dependentModule = findDependentModule(modules,
-                builder, unknownTypeQName.getPrefix(), line);
-        final TypeDefinitionBuilder lookedUpBuilder = findTypedefBuilderByName(
-                dependentModule, unknownTypeQName.getLocalName(),
-                builder.getName(), line);
-        return copyTypedefBuilder(lookedUpBuilder, true);
-    }
-
     private TypeConstraints findConstraints(
             final TypeAwareBuilder nodeToResolve,
             final TypeConstraints constraints,
@@ -510,7 +553,8 @@ public class YangParserImpl implements YangModelParser {
             fractionDigits = ext.getFractionDigits();
             constraints.setFractionDigits(fractionDigits);
             return findConstraints(
-                    findTypedefBuilder(ext.getQName(), modules, builder,
+                    findTypeDefinitionBuilder(nodeToResolve.getPath(), builder,
+                            ext.getQName().getLocalName(), builder.getName(),
                             nodeToResolve.getLine()), constraints, modules,
                     builder);
         } else if (referencedType instanceof UnknownType) {
@@ -531,8 +575,9 @@ public class YangParserImpl implements YangModelParser {
             final ModuleBuilder dependentModule = findDependentModule(modules,
                     builder, unknown.getQName().getPrefix(),
                     nodeToResolve.getLine());
-            final TypeDefinitionBuilder utBuilder = findTypedefBuilder(
-                    unknown.getQName(), modules, builder,
+            final TypeDefinitionBuilder utBuilder = findTypeDefinitionBuilder(
+                    nodeToResolve.getPath(), dependentModule, unknown
+                            .getQName().getLocalName(), builder.getName(),
                     nodeToResolve.getLine());
             return findConstraints(utBuilder, constraints, modules,
                     dependentModule);
@@ -544,38 +589,78 @@ public class YangParserImpl implements YangModelParser {
     }
 
     /**
-     * Go through all typedef statements from given module and search for one
-     * with given name
-     * 
-     * @param typedefs
-     *            typedef statements to search
-     * @param name
-     *            name of searched typedef
-     * @return typedef with name equals to given name
+     * 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
      */
-    private TypeDefinitionBuilder findTypedefBuilderByName(
-            final ModuleBuilder dependentModule, final String name,
+    private TypeDefinitionBuilder findTypeDefinitionBuilder(
+            SchemaPath dirtyNodeSchemaPath,
+            final ModuleBuilder dependentModule, final String typeName,
             final String currentModuleName, final int line) {
+        final List<QName> path = dirtyNodeSchemaPath.getPath();
         TypeDefinitionBuilder result = null;
-        final Set<TypeDefinitionBuilder> typedefs = dependentModule
+
+        Set<TypeDefinitionBuilder> typedefs = dependentModule
                 .getModuleTypedefs();
-        for (TypeDefinitionBuilder td : typedefs) {
-            if (td.getQName().getLocalName().equals(name)) {
-                result = td;
-                break;
+        result = findTdb(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 = findTdb(typedefs, typeName);
+                if (result != null) {
+                    break;
+                }
             }
         }
-        if (result == null) {
-            throw new YangParseException(currentModuleName, line,
-                    "Target module '" + dependentModule.getName()
-                            + "' does not contain typedef '" + name + "'.");
+
+        if (result != null) {
+            return result;
         }
-        return result;
+        throw new YangParseException(currentModuleName, line,
+                "Referenced type '" + typeName + "' not found.");
+    }
+
+    private TypeDefinitionBuilder findTdb(Set<TypeDefinitionBuilder> types,
+            String name) {
+        for (TypeDefinitionBuilder td : types) {
+            if (td.getQName().getLocalName().equals(name)) {
+                return td;
+            }
+        }
+        return null;
     }
 
     /**
      * Pull restriction from referenced type and add them to given constraints
-     * 
+     *
      * @param referencedType
      * @param constraints
      */
@@ -603,9 +688,9 @@ public class YangParserImpl implements YangModelParser {
     }
 
     /**
-     * Go through all augmentation definitions and resolve them. This method
-     * also finds referenced node and add child nodes to it.
-     * 
+     * Go through all augment definitions and resolve them. This method also
+     * finds augment target node and add child nodes to it.
+     *
      * @param modules
      *            all available modules
      */
@@ -629,7 +714,7 @@ public class YangParserImpl implements YangModelParser {
             // while all augments are not resolved
             final Iterator<ModuleBuilder> allModulesIterator = allModulesSet
                     .iterator();
-            while (!(module.getAugmentsResolved() == module.getAddedAugments()
+            while (!(module.getAugmentsResolved() == module.getAugments()
                     .size())) {
                 ModuleBuilder nextModule = null;
                 // try resolve other module augments
@@ -648,7 +733,7 @@ public class YangParserImpl implements YangModelParser {
     }
 
     /**
-     * 
+     *
      * @param modules
      *            all available modules
      * @param module
@@ -657,17 +742,16 @@ public class YangParserImpl implements YangModelParser {
     private void resolveAugment(
             final Map<String, TreeMap<Date, ModuleBuilder>> modules,
             final ModuleBuilder module) {
-        if (module.getAugmentsResolved() < module.getAddedAugments().size()) {
+        if (module.getAugmentsResolved() < module.getAugments().size()) {
             for (AugmentationSchemaBuilder augmentBuilder : module
-                    .getAddedAugments()) {
+                    .getAugments()) {
 
                 if (!augmentBuilder.isResolved()) {
                     final SchemaPath augmentTargetSchemaPath = augmentBuilder
                             .getTargetPath();
                     final List<QName> path = augmentTargetSchemaPath.getPath();
 
-                    int i = 0;
-                    final QName qname = path.get(i);
+                    final QName qname = path.get(0);
                     String prefix = qname.getPrefix();
                     if (prefix == null) {
                         prefix = module.getPrefix();
@@ -682,15 +766,18 @@ public class YangParserImpl implements YangModelParser {
                         if (childQName.getLocalName().equals(
                                 qname.getLocalName())) {
                             currentParent = child;
-                            i++;
                             break;
                         }
                     }
 
-                    for (; i < path.size(); i++) {
+                    if (currentParent == null) {
+                        continue;
+                    }
+
+                    for (int i = 1; i < path.size(); i++) {
                         final QName currentQName = path.get(i);
                         DataSchemaNodeBuilder newParent = null;
-                        for (DataSchemaNodeBuilder child : ((ChildNodeBuilder) currentParent)
+                        for (DataSchemaNodeBuilder child : ((DataNodeContainerBuilder) currentParent)
                                 .getChildNodes()) {
                             final QName childQName = child.getQName();
                             if (childQName.getLocalName().equals(
@@ -711,8 +798,14 @@ public class YangParserImpl implements YangModelParser {
                             .get(path.size() - 1);
                     if (currentQName.getLocalName().equals(
                             lastAugmentPathElement.getLocalName())) {
-                        ParserUtils.fillAugmentTarget(augmentBuilder,
-                                (ChildNodeBuilder) currentParent);
+
+                        if (currentParent instanceof ChoiceBuilder) {
+                            ParserUtils.fillAugmentTarget(augmentBuilder,
+                                    (ChoiceBuilder) currentParent);
+                        } else {
+                            ParserUtils.fillAugmentTarget(augmentBuilder,
+                                    (DataNodeContainerBuilder) currentParent);
+                        }
                         ((AugmentationTargetBuilder) currentParent)
                                 .addAugmentation(augmentBuilder);
                         SchemaPath oldPath = currentParent.getPath();
@@ -730,7 +823,7 @@ public class YangParserImpl implements YangModelParser {
     /**
      * Go through identity statements defined in current module and resolve
      * their 'base' statement if present.
-     * 
+     *
      * @param modules
      *            all modules
      * @param module
@@ -740,7 +833,7 @@ public class YangParserImpl implements YangModelParser {
             final Map<String, TreeMap<Date, ModuleBuilder>> modules,
             final ModuleBuilder module) {
         final Set<IdentitySchemaNodeBuilder> identities = module
-                .getAddedIdentities();
+                .getIdentities();
         for (IdentitySchemaNodeBuilder identity : identities) {
             final String baseIdentityName = identity.getBaseIdentityName();
             if (baseIdentityName != null) {
@@ -758,7 +851,7 @@ public class YangParserImpl implements YangModelParser {
                         modules, module, baseIdentityPrefix, identity.getLine());
 
                 final Set<IdentitySchemaNodeBuilder> dependentModuleIdentities = dependentModule
-                        .getAddedIdentities();
+                        .getIdentities();
                 for (IdentitySchemaNodeBuilder idBuilder : dependentModuleIdentities) {
                     if (idBuilder.getQName().getLocalName()
                             .equals(baseIdentityLocalName)) {
@@ -772,135 +865,71 @@ public class YangParserImpl implements YangModelParser {
     /**
      * Go through uses statements defined in current module and resolve their
      * refine statements.
-     * 
+     *
      * @param modules
      *            all modules
      * @param module
      *            module being resolved
      */
-    private void resolveUses(
+    private void resolveUsesRefines(
             final Map<String, TreeMap<Date, ModuleBuilder>> modules,
             final ModuleBuilder module) {
         final Map<List<String>, UsesNodeBuilder> moduleUses = module
-                .getAddedUsesNodes();
+                .getUsesNodes();
         for (Map.Entry<List<String>, UsesNodeBuilder> entry : moduleUses
                 .entrySet()) {
             final List<String> key = entry.getKey();
             final UsesNodeBuilder usesNode = entry.getValue();
+            final int line = usesNode.getLine();
 
             final String groupingName = key.get(key.size() - 1);
 
             for (RefineHolder refine : usesNode.getRefines()) {
-                // refine statements
-                final String defaultStr = refine.getDefaultStr();
-                final Boolean mandatory = refine.isMandatory();
-                final MustDefinition must = refine.getMust();
-                final Boolean presence = refine.isPresence();
-                final Integer min = refine.getMinElements();
-                final Integer max = refine.getMaxElements();
-                final List<UnknownSchemaNodeBuilder> unknownNodes = refine
-                        .getUnknownNodes();
-
-                Builder refineTarget = getRefineTargetBuilder(groupingName,
-                        refine, modules, module);
+                SchemaNodeBuilder refineTarget = getRefineNodeBuilderCopy(
+                        groupingName, refine, modules, module);
+                ParserUtils.checkRefine(refineTarget, refine);
+                ParserUtils.refineDefault(refineTarget, refine, line);
                 if (refineTarget instanceof LeafSchemaNodeBuilder) {
                     final LeafSchemaNodeBuilder leaf = (LeafSchemaNodeBuilder) refineTarget;
-                    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);
-                        }
-                    }
+                    ParserUtils.refineLeaf(leaf, refine, line);
                     usesNode.addRefineNode(leaf);
                 } else if (refineTarget instanceof ContainerSchemaNodeBuilder) {
                     final ContainerSchemaNodeBuilder container = (ContainerSchemaNodeBuilder) refineTarget;
-                    if (presence != null) {
-                        container.setPresence(presence);
-                    }
-                    if (must != null) {
-                        container.getConstraints().addMustDefinition(must);
-                    }
-                    if (unknownNodes != null) {
-                        for (UnknownSchemaNodeBuilder unknown : unknownNodes) {
-                            container.addUnknownSchemaNode(unknown);
-                        }
-                    }
+                    ParserUtils.refineContainer(container, refine, line);
                     usesNode.addRefineNode(container);
                 } else if (refineTarget instanceof ListSchemaNodeBuilder) {
                     final ListSchemaNodeBuilder list = (ListSchemaNodeBuilder) refineTarget;
-                    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);
-                        }
-                    }
+                    ParserUtils.refineList(list, refine, line);
+                    usesNode.addRefineNode(list);
                 } else if (refineTarget instanceof LeafListSchemaNodeBuilder) {
-                    final LeafListSchemaNodeBuilder leafList = (LeafListSchemaNodeBuilder) getRefineTargetBuilder(
-                            groupingName, refine, modules, module);
-                    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);
-                        }
-                    }
+                    final LeafListSchemaNodeBuilder leafList = (LeafListSchemaNodeBuilder) refineTarget;
+                    ParserUtils.refineLeafList(leafList, refine, line);
+                    usesNode.addRefineNode(leafList);
                 } else if (refineTarget instanceof ChoiceBuilder) {
                     final ChoiceBuilder choice = (ChoiceBuilder) refineTarget;
-                    if (defaultStr != null) {
-                        choice.setDefaultCase(defaultStr);
-                    }
-                    if (mandatory != null) {
-                        choice.getConstraints().setMandatory(mandatory);
-                    }
-                    if (unknownNodes != null) {
-                        for (UnknownSchemaNodeBuilder unknown : unknownNodes) {
-                            choice.addUnknownSchemaNode(unknown);
-                        }
-                    }
+                    ParserUtils.refineChoice(choice, refine, line);
+                    usesNode.addRefineNode(choice);
                 } else if (refineTarget instanceof AnyXmlBuilder) {
                     final AnyXmlBuilder anyXml = (AnyXmlBuilder) refineTarget;
-                    if (mandatory != null) {
-                        anyXml.getConstraints().setMandatory(mandatory);
-                    }
-                    if (must != null) {
-                        anyXml.getConstraints().addMustDefinition(must);
-                    }
-                    if (unknownNodes != null) {
-                        for (UnknownSchemaNodeBuilder unknown : unknownNodes) {
-                            anyXml.addUnknownSchemaNode(unknown);
-                        }
-                    }
+                    ParserUtils.refineAnyxml(anyXml, refine, line);
+                    usesNode.addRefineNode(anyXml);
+                } else if (refineTarget instanceof GroupingBuilder) {
+                    usesNode.addRefineNode(refineTarget);
+                } else if (refineTarget instanceof TypeDefinitionBuilder) {
+                    usesNode.addRefineNode(refineTarget);
                 }
             }
         }
     }
 
     /**
-     * Find original builder of refine node and return copy of this builder.
-     * 
+     * Find original builder of node to refine and return copy of this builder.
+     * <p>
+     * We must create and use a copy of builder to preserve original builder
+     * state, because this object will be refined (modified) and later added to
+     * {@link UsesNodeBuilder}.
+     * </p>
+     *
      * @param groupingPath
      *            path to grouping which contains node to refine
      * @param refine
@@ -909,11 +938,11 @@ public class YangParserImpl implements YangModelParser {
      *            all loaded modules
      * @param module
      *            current module
-     * @return copy of Builder object of node to be refined if it is present in
-     *         grouping, null otherwise
+     * @return copy of node to be refined if it is present in grouping, null
+     *         otherwise
      */
-    private Builder getRefineTargetBuilder(final String groupingPath,
-            final RefineHolder refine,
+    private SchemaNodeBuilder getRefineNodeBuilderCopy(
+            final String groupingPath, final RefineHolder refine,
             final Map<String, TreeMap<Date, ModuleBuilder>> modules,
             final ModuleBuilder module) {
         Builder result = null;
@@ -937,20 +966,26 @@ public class YangParserImpl implements YangModelParser {
         } else if (lookedUpBuilder instanceof AnyXmlBuilder) {
             result = ParserUtils
                     .copyAnyXmlBuilder((AnyXmlBuilder) lookedUpBuilder);
+        } else if (lookedUpBuilder instanceof GroupingBuilder) {
+            result = ParserUtils
+                    .copyGroupingBuilder((GroupingBuilder) lookedUpBuilder);
+        } else if (lookedUpBuilder instanceof TypeDefinitionBuilder) {
+            result = ParserUtils
+                    .copyTypedefBuilder((TypeDefinitionBuilderImpl) lookedUpBuilder);
         } else {
             throw new YangParseException(module.getName(), refine.getLine(),
                     "Target '" + refine.getName() + "' can not be refined");
         }
-        return result;
+        return (SchemaNodeBuilder) result;
     }
 
     /**
      * Find builder of refine node.
-     * 
+     *
      * @param groupingPath
      *            path to grouping which contains node to refine
-     * @param refineNodeName
-     *            name of node to be refined
+     * @param refine
+     *            object containing refine information
      * @param modules
      *            all loaded modules
      * @param module
@@ -962,6 +997,7 @@ public class YangParserImpl implements YangModelParser {
             final RefineHolder refine,
             final Map<String, TreeMap<Date, ModuleBuilder>> modules,
             final ModuleBuilder module) {
+        final String refineNodeName = refine.getName();
         final SchemaPath path = ParserUtils.parseUsesPath(groupingPath);
         final List<String> builderPath = new ArrayList<String>();
         String prefix = null;
@@ -975,12 +1011,30 @@ public class YangParserImpl implements YangModelParser {
 
         final ModuleBuilder dependentModule = findDependentModule(modules,
                 module, prefix, refine.getLine());
-        builderPath.add(0, "grouping");
         builderPath.add(0, dependentModule.getName());
-        final GroupingBuilder builder = (GroupingBuilder) dependentModule
-                .getNode(builderPath);
+        final GroupingBuilder builder = dependentModule
+                .getGrouping(builderPath);
 
-        return builder.getChildNode(refine.getName());
+        Builder result = builder.getChildNode(refineNodeName);
+        if (result == null) {
+            Set<GroupingBuilder> grps = builder.getGroupings();
+            for (GroupingBuilder gr : grps) {
+                if (gr.getQName().getLocalName().equals(refineNodeName)) {
+                    result = gr;
+                    break;
+                }
+            }
+        }
+        if (result == null) {
+            Set<TypeDefinitionBuilder> typedefs = builder.getTypeDefinitions();
+            for (TypeDefinitionBuilder typedef : typedefs) {
+                if (typedef.getQName().getLocalName().equals(refineNodeName)) {
+                    result = typedef;
+                    break;
+                }
+            }
+        }
+        return result;
     }
 
     private QName findFullQName(
@@ -1010,7 +1064,7 @@ public class YangParserImpl implements YangModelParser {
     private void resolveUnknownNodes(
             final Map<String, TreeMap<Date, ModuleBuilder>> modules,
             final ModuleBuilder module) {
-        for (UnknownSchemaNodeBuilder usnb : module.getAddedUnknownNodes()) {
+        for (UnknownSchemaNodeBuilder usnb : module.getUnknownNodes()) {
             QName nodeType = usnb.getNodeType();
             if (nodeType.getNamespace() == null
                     || nodeType.getRevision() == null) {
@@ -1033,13 +1087,15 @@ public class YangParserImpl implements YangModelParser {
 
     /**
      * 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
      */
     private ModuleBuilder findDependentModule(
@@ -1086,82 +1142,4 @@ public class YangParserImpl implements YangModelParser {
         return dependentModule;
     }
 
-    private static class SchemaContextImpl implements SchemaContext {
-        private final Set<Module> modules;
-
-        private SchemaContextImpl(final Set<Module> modules) {
-            this.modules = modules;
-        }
-
-        @Override
-        public Set<DataSchemaNode> getDataDefinitions() {
-            final Set<DataSchemaNode> dataDefs = new HashSet<DataSchemaNode>();
-            for (Module m : modules) {
-                dataDefs.addAll(m.getChildNodes());
-            }
-            return dataDefs;
-        }
-
-        @Override
-        public Set<Module> getModules() {
-            return modules;
-        }
-
-        @Override
-        public Set<NotificationDefinition> getNotifications() {
-            final Set<NotificationDefinition> notifications = new HashSet<NotificationDefinition>();
-            for (Module m : modules) {
-                notifications.addAll(m.getNotifications());
-            }
-            return notifications;
-        }
-
-        @Override
-        public Set<RpcDefinition> getOperations() {
-            final Set<RpcDefinition> rpcs = new HashSet<RpcDefinition>();
-            for (Module m : modules) {
-                rpcs.addAll(m.getRpcs());
-            }
-            return rpcs;
-        }
-
-        @Override
-        public Set<ExtensionDefinition> getExtensions() {
-            final Set<ExtensionDefinition> extensions = new HashSet<ExtensionDefinition>();
-            for (Module m : modules) {
-                extensions.addAll(m.getExtensionSchemaNodes());
-            }
-            return extensions;
-        }
-
-        @Override
-        public Module findModuleByName(final String name, final Date revision) {
-            if (name != null) {
-                for (final Module module : modules) {
-                    if (revision == null) {
-                        if (module.getName().equals(name)) {
-                            return module;
-                        }
-                    } else if (module.getName().equals(name)
-                            && module.getRevision().equals(revision)) {
-                        return module;
-                    }
-                }
-            }
-            return null;
-        }
-
-        @Override
-        public Module findModuleByNamespace(final URI namespace) {
-            if (namespace != null) {
-                for (final Module module : modules) {
-                    if (module.getNamespace().equals(namespace)) {
-                        return module;
-                    }
-                }
-            }
-            return null;
-        }
-    }
-
 }