Merge "Fix for Bug 586."
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / impl / YangParserImpl.java
index 09862a464776a14882225d937db0e7487a99a86d..7448f130b2c3f615ab22d4e2f695b7ccc4bd1879 100644 (file)
@@ -7,31 +7,30 @@
  */
 package org.opendaylight.yangtools.yang.parser.impl;
 
-import static org.opendaylight.yangtools.yang.parser.util.ParserUtils.*;
-import static org.opendaylight.yangtools.yang.parser.util.TypeUtils.resolveType;
-import static org.opendaylight.yangtools.yang.parser.util.TypeUtils.resolveTypeUnion;
-import static org.opendaylight.yangtools.yang.parser.util.TypeUtils.resolveTypeUnionWithContext;
-import static org.opendaylight.yangtools.yang.parser.util.TypeUtils.resolveTypeWithContext;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.util.*;
-
+import com.google.common.base.Preconditions;
 import org.antlr.v4.runtime.ANTLRInputStream;
 import org.antlr.v4.runtime.CommonTokenStream;
 import org.antlr.v4.runtime.tree.ParseTree;
 import org.antlr.v4.runtime.tree.ParseTreeWalker;
+import org.apache.commons.io.IOUtils;
 import org.opendaylight.yangtools.antlrv4.code.gen.YangLexer;
 import org.opendaylight.yangtools.antlrv4.code.gen.YangParser;
 import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.YangContext;
 import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.*;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ExtensionDefinition;
+import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
+import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier;
+import org.opendaylight.yangtools.yang.model.api.ModuleImport;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 import org.opendaylight.yangtools.yang.model.parser.api.YangModelParser;
 import org.opendaylight.yangtools.yang.parser.builder.api.AugmentationSchemaBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.api.AugmentationTargetBuilder;
 import org.opendaylight.yangtools.yang.parser.builder.api.Builder;
 import org.opendaylight.yangtools.yang.parser.builder.api.DataNodeContainerBuilder;
 import org.opendaylight.yangtools.yang.parser.builder.api.DataSchemaNodeBuilder;
@@ -40,18 +39,66 @@ import org.opendaylight.yangtools.yang.parser.builder.api.SchemaNodeBuilder;
 import org.opendaylight.yangtools.yang.parser.builder.api.TypeAwareBuilder;
 import org.opendaylight.yangtools.yang.parser.builder.api.TypeDefinitionBuilder;
 import org.opendaylight.yangtools.yang.parser.builder.api.UsesNodeBuilder;
-import org.opendaylight.yangtools.yang.parser.builder.impl.*;
+import org.opendaylight.yangtools.yang.parser.builder.impl.ChoiceBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.impl.ChoiceCaseBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.impl.DeviationBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.impl.ExtensionBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.impl.IdentitySchemaNodeBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.impl.IdentityrefTypeBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.impl.ModuleBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.impl.ModuleBuilder.ModuleImpl;
+import org.opendaylight.yangtools.yang.parser.builder.impl.UnionTypeBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.impl.UnknownSchemaNodeBuilder;
 import org.opendaylight.yangtools.yang.parser.util.Comparators;
 import org.opendaylight.yangtools.yang.parser.util.GroupingSort;
 import org.opendaylight.yangtools.yang.parser.util.GroupingUtils;
 import org.opendaylight.yangtools.yang.parser.util.ModuleDependencySort;
+import org.opendaylight.yangtools.yang.parser.util.NamedByteArrayInputStream;
+import org.opendaylight.yangtools.yang.parser.util.NamedInputStream;
 import org.opendaylight.yangtools.yang.parser.util.ParserUtils;
 import org.opendaylight.yangtools.yang.parser.util.YangParseException;
 import org.opendaylight.yangtools.yang.validator.YangModelBasicValidator;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Preconditions;
+import java.io.File;
+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.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.opendaylight.yangtools.yang.parser.util.ParserUtils.fillAugmentTarget;
+import static org.opendaylight.yangtools.yang.parser.util.ParserUtils.findBaseIdentity;
+import static org.opendaylight.yangtools.yang.parser.util.ParserUtils.findBaseIdentityFromContext;
+import static org.opendaylight.yangtools.yang.parser.util.ParserUtils.findModuleFromBuilders;
+import static org.opendaylight.yangtools.yang.parser.util.ParserUtils.findModuleFromContext;
+import static org.opendaylight.yangtools.yang.parser.util.ParserUtils.findSchemaNode;
+import static org.opendaylight.yangtools.yang.parser.util.ParserUtils.findSchemaNodeInModule;
+import static org.opendaylight.yangtools.yang.parser.util.ParserUtils.processAugmentation;
+import static org.opendaylight.yangtools.yang.parser.util.ParserUtils.setNodeAddedByUses;
+import static org.opendaylight.yangtools.yang.parser.util.ParserUtils.wrapChildNode;
+import static org.opendaylight.yangtools.yang.parser.util.ParserUtils.wrapChildNodes;
+import static org.opendaylight.yangtools.yang.parser.util.ParserUtils.wrapGroupings;
+import static org.opendaylight.yangtools.yang.parser.util.ParserUtils.wrapTypedefs;
+import static org.opendaylight.yangtools.yang.parser.util.ParserUtils.wrapUnknownNodes;
+import static org.opendaylight.yangtools.yang.parser.util.TypeUtils.resolveType;
+import static org.opendaylight.yangtools.yang.parser.util.TypeUtils.resolveTypeUnion;
+import static org.opendaylight.yangtools.yang.parser.util.TypeUtils.resolveTypeUnionWithContext;
+import static org.opendaylight.yangtools.yang.parser.util.TypeUtils.resolveTypeWithContext;
 
 
 public final class YangParserImpl implements YangModelParser {
@@ -67,7 +114,7 @@ public final class YangParserImpl implements YangModelParser {
 
         final String yangFileName = yangFile.getName();
         final String[] fileList = directory.list();
-        Preconditions.checkNotNull(fileList, directory + " not found");
+        checkNotNull(fileList, directory + " not found");
 
         FileInputStream yangFileStream = null;
         LinkedHashMap<InputStream, File> streamToFileMap = new LinkedHashMap<>();
@@ -190,6 +237,7 @@ public final class YangParserImpl implements YangModelParser {
         final Map<InputStream, File> inputStreams = new HashMap<>();
         for (final File yangFile : yangFiles) {
             try {
+
                 inputStreams.put(new FileInputStream(yangFile), yangFile);
             } catch (FileNotFoundException e) {
                 LOG.warn("Exception while reading yang file: " + yangFile.getName(), e);
@@ -219,30 +267,84 @@ public final class YangParserImpl implements YangModelParser {
         return result;
     }
 
+    // TODO: fix exception handling
     @Override
     public Map<InputStream, Module> parseYangModelsFromStreamsMapped(final List<InputStream> yangModelStreams) {
         if (yangModelStreams == null) {
             return Collections.emptyMap();
         }
 
-        Map<ModuleBuilder, InputStream> builderToStreamMap = new HashMap<>();
-        Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModuleBuilders(yangModelStreams, builderToStreamMap,
+
+        // copy input streams so that they can be read more than once
+        Map<InputStream/*array backed copy */, InputStream/* original for returning*/> arrayBackedToOriginalInputStreams = new HashMap<>();
+        for (final InputStream originalIS : yangModelStreams) {
+            InputStream arrayBackedIs;
+            try {
+                arrayBackedIs = NamedByteArrayInputStream.create(originalIS);
+            } catch (IOException e) {
+                // FIXME: throw IOException here
+                throw new IllegalStateException("Can not get yang as String from " + originalIS, e);
+            }
+            arrayBackedToOriginalInputStreams.put(arrayBackedIs, originalIS);
+        }
+
+        // it would be better if all code from here used string representation of yang sources instead of input streams
+        Map<ModuleBuilder, InputStream> builderToStreamMap = new HashMap<>(); // FIXME: do not modify input parameter
+        Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModuleBuilders(new ArrayList<>(arrayBackedToOriginalInputStreams.keySet()),
+                builderToStreamMap,
                 null);
-        Map<InputStream, Module> result = new LinkedHashMap<>();
+
+
+        // TODO move deeper
+        for(TreeMap<Date, ModuleBuilder> value : modules.values()) {
+            Collection<ModuleBuilder> values = value.values();
+            for(ModuleBuilder builder: values) {
+                InputStream is = builderToStreamMap.get(builder);
+                try {
+                    is.reset();
+                } catch (IOException e) {
+                    // this cannot happen because it is ByteArrayInputStream
+                    throw new IllegalStateException("Possible error in code", e);
+                }
+                String content;
+                try {
+                    content = IOUtils.toString(is);
+                } catch (IOException e) {
+                    // this cannot happen because it is ByteArrayInputStream
+                    throw new IllegalStateException("Possible error in code", e);
+                }
+                builder.setSource(content);
+            }
+        }
+
+
         Map<ModuleBuilder, Module> builderToModuleMap = build(modules);
+
         Set<ModuleBuilder> keyset = builderToModuleMap.keySet();
         List<ModuleBuilder> sorted = ModuleDependencySort.sort(keyset.toArray(new ModuleBuilder[keyset.size()]));
+        Map<InputStream, Module> result = new LinkedHashMap<>();
         for (ModuleBuilder key : sorted) {
-            result.put(builderToStreamMap.get(key), builderToModuleMap.get(key));
+            Module value = checkNotNull(builderToModuleMap.get(key), "Cannot get module for %s", key);
+            InputStream arrayBackedIS = checkNotNull(builderToStreamMap.get(key), "Cannot get is for %s", key);
+            InputStream originalIS = arrayBackedToOriginalInputStreams.get(arrayBackedIS);
+            result.put(originalIS, value);
         }
         return result;
     }
 
     @Override
     public SchemaContext resolveSchemaContext(final Set<Module> modules) {
-        return new SchemaContextImpl(modules);
+        // after merging parse method with this one, add support for getting submodule sources.
+        Map<ModuleIdentifier, String> identifiersToSources = new HashMap<>();
+        for(Module module: modules) {
+            ModuleImpl moduleImpl = (ModuleImpl) module;
+            identifiersToSources.put(module, moduleImpl.getSource());
+        }
+        return new SchemaContextImpl(modules, identifiersToSources);
     }
 
+    // FIXME: why a list is required?
+    // FIXME: streamToBuilderMap is output of this method, not input
     private Map<InputStream, ModuleBuilder> parseModuleBuilders(List<InputStream> inputStreams,
             Map<ModuleBuilder, InputStream> streamToBuilderMap) {
         Map<InputStream, ModuleBuilder> modules = parseBuilders(inputStreams, streamToBuilderMap);
@@ -250,6 +352,8 @@ public final class YangParserImpl implements YangModelParser {
         return result;
     }
 
+    // FIXME: why a list is required?
+    // FIXME: streamToBuilderMap is output of this method, not input
     private Map<InputStream, ModuleBuilder> parseBuilders(List<InputStream> inputStreams,
             Map<ModuleBuilder, InputStream> streamToBuilderMap) {
         final ParseTreeWalker walker = new ParseTreeWalker();
@@ -261,11 +365,17 @@ public final class YangParserImpl implements YangModelParser {
 
         YangParserListenerImpl yangModelParser;
         for (Map.Entry<InputStream, ParseTree> entry : trees.entrySet()) {
-            yangModelParser = new YangParserListenerImpl();
+            InputStream is = entry.getKey();
+            String path = null;
+            if (is instanceof NamedInputStream) {
+                path = is.toString();
+            }
+            yangModelParser = new YangParserListenerImpl(path);
             walker.walk(yangModelParser, entry.getValue());
             ModuleBuilder moduleBuilder = yangModelParser.getModuleBuilder();
 
             // We expect the order of trees and streams has to be the same
+            // FIXME: input parameters should be treated as immutable
             streamToBuilderMap.put(moduleBuilder, entry.getKey());
 
             builders.put(entry.getKey(), moduleBuilder);
@@ -351,6 +461,8 @@ public final class YangParserImpl implements YangModelParser {
         module.getAllUnknownNodes().addAll(submodule.getAllUnknownNodes());
     }
 
+    // FIXME: why a list is required?
+    // FIXME: streamToBuilderMap is output of this method, not input
     private Map<String, TreeMap<Date, ModuleBuilder>> resolveModuleBuilders(final List<InputStream> yangFileStreams,
             final Map<ModuleBuilder, InputStream> streamToBuilderMap, final SchemaContext context) {
         Map<InputStream, ModuleBuilder> parsedBuilders = parseModuleBuilders(yangFileStreams, streamToBuilderMap);
@@ -432,6 +544,7 @@ public final class YangParserImpl implements YangModelParser {
         }
     }
 
+    // FIXME: why a list is required?
     private Map<InputStream, ParseTree> parseStreams(final List<InputStream> yangStreams) {
         final Map<InputStream, ParseTree> trees = new HashMap<>();
         for (InputStream yangStream : yangStreams) {
@@ -453,6 +566,7 @@ public final class YangParserImpl implements YangModelParser {
             result = parser.yang();
             errorListener.validate();
         } catch (IOException e) {
+            // TODO: fix this ASAP
             LOG.warn("Exception while reading yang file: " + yangStream, e);
         }
         return result;
@@ -473,14 +587,33 @@ public final class YangParserImpl implements YangModelParser {
         return result;
     }
 
+    /**
+     * Creates builder-to-module map based on given modules. Method first
+     * resolve unresolved type references, instantiate groupings through uses
+     * statements and perform augmentation.
+     *
+     * Node resolving must be performed in following order:
+     * <ol>
+     * <li>
+     * unresolved type references</li>
+     * <li>
+     * uses in groupings</li>
+     * <li>
+     * uses in other nodes</li>
+     * <li>
+     * augments</li>
+     * </ol>
+     *
+     * @param modules
+     *            all loaded modules
+     * @return modules mapped on their builders
+     */
     private Map<ModuleBuilder, Module> build(final Map<String, TreeMap<Date, ModuleBuilder>> modules) {
-        // fix unresolved nodes
         resolveDirtyNodes(modules);
         resolveAugmentsTargetPath(modules, null);
         resolveUsesTargetGrouping(modules, null);
         resolveUsesForGroupings(modules, null);
         resolveUsesForNodes(modules, null);
-        resolveListsKey(modules);
         resolveAugments(modules, null);
         resolveDeviations(modules);
 
@@ -496,15 +629,36 @@ public final class YangParserImpl implements YangModelParser {
         return result;
     }
 
+    /**
+     * Creates builder-to-module map based on given modules. Method first
+     * resolve unresolved type references, instantiate groupings through uses
+     * statements and perform augmentation.
+     *
+     * Node resolving must be performed in following order:
+     * <ol>
+     * <li>
+     * unresolved type references</li>
+     * <li>
+     * uses in groupings</li>
+     * <li>
+     * uses in other nodes</li>
+     * <li>
+     * augments</li>
+     * </ol>
+     *
+     * @param modules
+     *            all loaded modules
+     * @param context
+     *            SchemaContext containing already resolved modules
+     * @return modules mapped on their builders
+     */
     private Map<ModuleBuilder, Module> buildWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
             final SchemaContext context) {
-        // fix unresolved nodes
         resolvedDirtyNodesWithContext(modules, context);
         resolveAugmentsTargetPath(modules, context);
         resolveUsesTargetGrouping(modules, context);
         resolveUsesForGroupings(modules, context);
         resolveUsesForNodes(modules, context);
-        resolveListsKey(modules);
         resolveAugments(modules, context);
         resolveDeviationsWithContext(modules, context);
 
@@ -520,6 +674,12 @@ public final class YangParserImpl implements YangModelParser {
         return result;
     }
 
+    /**
+     * Resolve all unresolved type references.
+     *
+     * @param modules
+     *            all loaded modules
+     */
     private void resolveDirtyNodes(final Map<String, TreeMap<Date, ModuleBuilder>> modules) {
         for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
             for (Map.Entry<Date, ModuleBuilder> childEntry : entry.getValue().entrySet()) {
@@ -531,6 +691,14 @@ public final class YangParserImpl implements YangModelParser {
         }
     }
 
+    /**
+     * Resolve all unresolved type references.
+     *
+     * @param modules
+     *            all loaded modules
+     * @param context
+     *            SchemaContext containing already resolved modules
+     */
     private void resolvedDirtyNodesWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
             final SchemaContext context) {
         for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
@@ -599,10 +767,13 @@ public final class YangParserImpl implements YangModelParser {
     }
 
     /**
-     * Correct augment target path.
+     * Traverse through augmentations of modules and fix their child nodes
+     * schema path.
      *
      * @param modules
      *            all loaded modules
+     * @param context
+     *            SchemaContext containing already resolved modules
      */
     private void resolveAugmentsTargetPath(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
             SchemaContext context) {
@@ -619,6 +790,16 @@ public final class YangParserImpl implements YangModelParser {
         }
     }
 
+    /**
+     * Find augment target and set correct schema path for all its child nodes.
+     *
+     * @param modules
+     *            all loaded modules
+     * @param augment
+     *            augment to resolve
+     * @param context
+     *            SchemaContext containing already resolved modules
+     */
     private void setCorrectAugmentTargetPath(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
             final AugmentationSchemaBuilder augment, final SchemaContext context) {
         ModuleBuilder module = ParserUtils.getParentModule(augment);
@@ -650,11 +831,9 @@ public final class YangParserImpl implements YangModelParser {
                 newPath.add(new QName(ns, revision, prefix, qn.getLocalName()));
             }
         } else {
-
             for (QName qn : oldPath) {
                 URI ns = module.getNamespace();
                 Date rev = module.getRevision();
-                String pref = module.getPrefix();
                 String localPrefix = qn.getPrefix();
                 if (localPrefix != null && !("".equals(localPrefix))) {
                     ModuleBuilder currentModule = ParserUtils.findModuleFromBuilders(modules, module, localPrefix,
@@ -667,23 +846,30 @@ public final class YangParserImpl implements YangModelParser {
                         }
                         ns = m.getNamespace();
                         rev = m.getRevision();
-                        pref = m.getPrefix();
                     } else {
                         ns = currentModule.getNamespace();
                         rev = currentModule.getRevision();
-                        pref = currentModule.getPrefix();
                     }
                 }
-                newPath.add(new QName(ns, rev, pref, qn.getLocalName()));
+                newPath.add(new QName(ns, rev, localPrefix, qn.getLocalName()));
             }
         }
-        augment.setTargetNodeSchemaPath(new SchemaPath(newPath, augment.getTargetPath().isAbsolute()));
+        augment.setTargetNodeSchemaPath(new SchemaPath(newPath, true));
 
         for (DataSchemaNodeBuilder childNode : augment.getChildNodeBuilders()) {
             correctPathForAugmentNodes(childNode, augment.getTargetNodeSchemaPath());
         }
     }
 
+    /**
+     * Set new schema path to node and all its child nodes based on given parent
+     * path. This method do not change the namespace.
+     *
+     * @param node
+     *            node which schema path should be updated
+     * @param parentPath
+     *            schema path of parent node
+     */
     private void correctPathForAugmentNodes(DataSchemaNodeBuilder node, SchemaPath parentPath) {
         SchemaPath newPath = ParserUtils.createSchemaPath(parentPath, node.getQName());
         node.setPath(newPath);
@@ -728,9 +914,7 @@ public final class YangParserImpl implements YangModelParser {
     }
 
     /**
-     * Go through all augment definitions and resolve them. This method works in
-     * same way as {@link #resolveAugments(Map)} except that if target node is
-     * not found in loaded modules, it search for target node in given context.
+     * Go through all augment definitions and resolve them.
      *
      * @param modules
      *            all loaded modules
@@ -770,6 +954,19 @@ public final class YangParserImpl implements YangModelParser {
         }
     }
 
+    /**
+     * Perform augmentation defined under uses statement.
+     *
+     * @param augment
+     *            augment to resolve
+     * @param module
+     *            current module
+     * @param modules
+     *            all loaded modules
+     * @param context
+     *            SchemaContext containing already resolved modules
+     * @return true if augment process succeed
+     */
     private boolean resolveUsesAugment(final AugmentationSchemaBuilder augment, final ModuleBuilder module,
             final Map<String, TreeMap<Date, ModuleBuilder>> modules, final SchemaContext context) {
         if (augment.isResolved()) {
@@ -780,16 +977,35 @@ public final class YangParserImpl implements YangModelParser {
         DataNodeContainerBuilder parentNode = usesNode.getParent();
         SchemaNodeBuilder targetNode;
         if (parentNode instanceof ModuleBuilder) {
-            targetNode = findSchemaNodeInModule(augment.getTargetPath().getPath(), (ModuleBuilder)parentNode);
+            targetNode = findSchemaNodeInModule(augment.getTargetPath().getPath(), (ModuleBuilder) parentNode);
         } else {
-            targetNode = findSchemaNode(augment.getTargetPath().getPath(), (SchemaNodeBuilder)parentNode);
+            targetNode = findSchemaNode(augment.getTargetPath().getPath(), (SchemaNodeBuilder) parentNode);
         }
 
-        fillAugmentTarget(augment, targetNode);
-        augment.setResolved(true);
-        return true;
+        if (targetNode instanceof AugmentationTargetBuilder) {
+            fillAugmentTarget(augment, targetNode);
+            ((AugmentationTargetBuilder) targetNode).addAugmentation(augment);
+            augment.setResolved(true);
+            return true;
+        } else {
+            throw new YangParseException(module.getName(), augment.getLine(),
+                    "Failed to resolve augment in uses. Invalid augment target: " + targetNode);
+        }
     }
 
+    /**
+     * Find augment target module and perform augmentation.
+     *
+     * @param augment
+     *            augment to resolve
+     * @param module
+     *            current module
+     * @param modules
+     *            all loaded modules
+     * @param context
+     *            SchemaContext containing already resolved modules
+     * @return true if augment process succeed
+     */
     private boolean resolveAugment(final AugmentationSchemaBuilder augment, final ModuleBuilder module,
             final Map<String, TreeMap<Date, ModuleBuilder>> modules, final SchemaContext context) {
         if (augment.isResolved()) {
@@ -941,6 +1157,14 @@ public final class YangParserImpl implements YangModelParser {
         }
     }
 
+    /**
+     * Resolve uses statements defined in groupings.
+     *
+     * @param modules
+     *            all loaded modules
+     * @param context
+     *            SchemaContext containing already resolved modules
+     */
     private void resolveUsesForGroupings(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final SchemaContext context) {
         final Set<GroupingBuilder> allGroupings = new HashSet<>();
         for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
@@ -959,6 +1183,14 @@ public final class YangParserImpl implements YangModelParser {
         }
     }
 
+    /**
+     * Resolve uses statements.
+     *
+     * @param modules
+     *            all loaded modules
+     * @param context
+     *            SchemaContext containing already resolved modules
+     */
     private void resolveUsesForNodes(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final SchemaContext context) {
         for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
             for (Map.Entry<Date, ModuleBuilder> inner : entry.getValue().entrySet()) {
@@ -972,6 +1204,17 @@ public final class YangParserImpl implements YangModelParser {
         }
     }
 
+    /**
+     * Find target grouping and copy its child nodes to current location with
+     * new namespace.
+     *
+     * @param usesNode
+     *            uses node to resolve
+     * @param modules
+     *            all loaded modules
+     * @param context
+     *            SchemaContext containing already resolved modules
+     */
     private void resolveUses(UsesNodeBuilder usesNode,
             final Map<String, TreeMap<Date, ModuleBuilder>> modules, final SchemaContext context) {
         if (!usesNode.isResolved()) {
@@ -998,6 +1241,17 @@ public final class YangParserImpl implements YangModelParser {
         }
     }
 
+    /**
+     * Copy target grouping child nodes to current location with
+     * new namespace.
+     *
+     * @param usesNode
+     *            uses node to resolve
+     * @param modules
+     *            all loaded modules
+     * @param context
+     *            SchemaContext containing already resolved modules
+     */
     private void resolveUsesWithContext(UsesNodeBuilder usesNode) {
         final int line = usesNode.getLine();
         DataNodeContainerBuilder parent = usesNode.getParent();
@@ -1053,28 +1307,15 @@ public final class YangParserImpl implements YangModelParser {
         }
     }
 
-    private void resolveListsKey(final Map<String, TreeMap<Date, ModuleBuilder>> modules) {
-        for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
-            for (Map.Entry<Date, ModuleBuilder> inner : entry.getValue().entrySet()) {
-                ModuleBuilder module = inner.getValue();
-                List<ListSchemaNodeBuilder> allLists = module.getAllLists();
-                for (ListSchemaNodeBuilder list : allLists) {
-                    List<String> keys = list.getKeys();
-                    if (keys == null) {
-                        list.setKeyDefinition(Collections.<QName> emptyList());
-                    } else {
-                        List<QName> qnames = new ArrayList<>();
-                        for (String key : keys) {
-                            qnames.add(list.getDataChildByName(key).getQName());
-                        }
-                        list.setKeyDefinition(qnames);
-                    }
-
-                }
-            }
-        }
-    }
-
+    /**
+     * Try to find extension builder describing this unknown node and assign it
+     * to unknown node builder.
+     *
+     * @param modules
+     *            all loaded modules
+     * @param module
+     *            current module
+     */
     private void resolveUnknownNodes(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
         for (UnknownSchemaNodeBuilder usnb : module.getAllUnknownNodes()) {
             QName nodeType = usnb.getNodeType();
@@ -1095,6 +1336,18 @@ public final class YangParserImpl implements YangModelParser {
         }
     }
 
+    /**
+     * Try to find extension builder describing this unknown node and assign it
+     * to unknown node builder. If extension is not found in loaded modules, try
+     * to find it in context.
+     *
+     * @param modules
+     *            all loaded modules
+     * @param module
+     *            current module
+     * @param context
+     *            SchemaContext containing already resolved modules
+     */
     private void resolveUnknownNodesWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
             final ModuleBuilder module, final SchemaContext context) {
         for (UnknownSchemaNodeBuilder usnb : module.getAllUnknownNodes()) {