Moved parsing of unknown nodes from implementation to abstract classes.
[controller.git] / opendaylight / sal / yang-prototype / code-generator / yang-model-parser-impl / src / main / java / org / opendaylight / controller / yang / parser / impl / YangParserListenerImpl.java
index b853dcf2a89b29827bd4478a99eb5516ae55182d..155deced668e9bb19462c64eab3c752fd7ee1acb 100644 (file)
@@ -7,19 +7,18 @@
  */
 package org.opendaylight.controller.yang.parser.impl;
 
-import static org.opendaylight.controller.yang.parser.util.YangModelBuilderUtil.*;
+import static org.opendaylight.controller.yang.parser.util.ParserListenerUtils.*;
 
 import java.net.URI;
 import java.text.DateFormat;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
-import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 import java.util.Stack;
 
 import org.antlr.v4.runtime.tree.ParseTree;
-import org.opendaylight.controller.antlrv4.code.gen.YangParser;
+import org.opendaylight.controller.antlrv4.code.gen.*;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Argument_stmtContext;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Base_stmtContext;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Contact_stmtContext;
@@ -50,14 +49,14 @@ import org.opendaylight.controller.antlrv4.code.gen.YangParser.Type_body_stmtsCo
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Units_stmtContext;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.When_stmtContext;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Yang_version_stmtContext;
-import org.opendaylight.controller.antlrv4.code.gen.YangParserBaseListener;
 import org.opendaylight.controller.yang.common.QName;
 import org.opendaylight.controller.yang.model.api.SchemaPath;
-import org.opendaylight.controller.yang.model.api.Status;
 import org.opendaylight.controller.yang.model.api.TypeDefinition;
 import org.opendaylight.controller.yang.model.util.YangTypesConverter;
 import org.opendaylight.controller.yang.parser.builder.api.AugmentationSchemaBuilder;
 import org.opendaylight.controller.yang.parser.builder.api.GroupingBuilder;
+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.ChoiceCaseBuilder;
@@ -72,7 +71,6 @@ import org.opendaylight.controller.yang.parser.builder.impl.ListSchemaNodeBuilde
 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.RpcDefinitionBuilder;
-import org.opendaylight.controller.yang.parser.builder.impl.TypedefBuilder;
 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.RefineHolder;
@@ -80,24 +78,21 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public final class YangParserListenerImpl extends YangParserBaseListener {
-
-    private static final Logger logger = LoggerFactory
-            .getLogger(YangParserListenerImpl.class);
+    private static final Logger logger = LoggerFactory.getLogger(YangParserListenerImpl.class);
 
     private ModuleBuilder moduleBuilder;
-
     private String moduleName;
     private URI namespace;
     private String yangModelPrefix;
     private Date revision = new Date(0L);
 
-    public final static DateFormat simpleDateFormat = new SimpleDateFormat(
-            "yyyy-MM-dd");
+    public final static DateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
     private final Stack<String> actualPath = new Stack<String>();
 
     @Override
     public void enterModule_stmt(YangParser.Module_stmtContext ctx) {
         moduleName = stringFromNode(ctx);
+        logger.debug("enter module " + moduleName);
         actualPath.push(moduleName);
         moduleBuilder = new ModuleBuilder(moduleName);
 
@@ -122,14 +117,12 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
 
     @Override
     public void exitModule_stmt(YangParser.Module_stmtContext ctx) {
-        final String moduleName = actualPath.pop();
-        logger.debug("Exiting module " + moduleName);
+        exitLog("module", actualPath.pop());
     }
 
     @Override
-    public void enterModule_header_stmts(final Module_header_stmtsContext ctx) {
-        super.enterModule_header_stmts(ctx);
-
+    public void enterModule_header_stmts(Module_header_stmtsContext ctx) {
+        enterLog("module_header", "", ctx.getStart().getLine());
         String yangVersion = null;
         for (int i = 0; i < ctx.getChildCount(); ++i) {
             final ParseTree treeNode = ctx.getChild(i);
@@ -137,11 +130,14 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
                 final String namespaceStr = stringFromNode(treeNode);
                 namespace = URI.create(namespaceStr);
                 moduleBuilder.setNamespace(namespace);
+                setLog("namespace", namespaceStr);
             } else if (treeNode instanceof Prefix_stmtContext) {
                 yangModelPrefix = stringFromNode(treeNode);
                 moduleBuilder.setPrefix(yangModelPrefix);
+                setLog("prefix", yangModelPrefix);
             } else if (treeNode instanceof Yang_version_stmtContext) {
                 yangVersion = stringFromNode(treeNode);
+                setLog("yang-version", yangVersion);
             }
         }
 
@@ -151,45 +147,57 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
         moduleBuilder.setYangVersion(yangVersion);
     }
 
+    @Override
+    public void exitModule_header_stmts(Module_header_stmtsContext ctx) {
+        exitLog("module_header", "");
+    }
+
     @Override
     public void enterMeta_stmts(YangParser.Meta_stmtsContext ctx) {
+        enterLog("meta_stmt", "", ctx.getStart().getLine());
         for (int i = 0; i < ctx.getChildCount(); i++) {
             ParseTree child = ctx.getChild(i);
             if (child instanceof Organization_stmtContext) {
                 final String organization = stringFromNode(child);
                 moduleBuilder.setOrganization(organization);
+                setLog("organization", organization);
             } else if (child instanceof Contact_stmtContext) {
                 final String contact = stringFromNode(child);
                 moduleBuilder.setContact(contact);
+                setLog("contact", contact);
             } else if (child instanceof Description_stmtContext) {
                 final String description = stringFromNode(child);
                 moduleBuilder.setDescription(description);
+                setLog("description", description);
             } else if (child instanceof Reference_stmtContext) {
                 final String reference = stringFromNode(child);
                 moduleBuilder.setReference(reference);
+                setLog("reference", reference);
             }
         }
     }
 
     @Override
-    public void exitSubmodule_header_stmts(
-            YangParser.Submodule_header_stmtsContext ctx) {
-        final String submodule = actualPath.pop();
-        logger.debug("exiting submodule " + submodule);
+    public void exitMeta_stmts(YangParser.Meta_stmtsContext ctx) {
+        exitLog("meta_stmt", "");
     }
 
     @Override
     public void enterRevision_stmts(Revision_stmtsContext ctx) {
-        if (ctx != null) {
-            for (int i = 0; i < ctx.getChildCount(); ++i) {
-                final ParseTree treeNode = ctx.getChild(i);
-                if (treeNode instanceof Revision_stmtContext) {
-                    updateRevisionForRevisionStatement(treeNode);
-                }
+        enterLog("revisions", "", ctx.getStart().getLine());
+        for (int i = 0; i < ctx.getChildCount(); ++i) {
+            final ParseTree treeNode = ctx.getChild(i);
+            if (treeNode instanceof Revision_stmtContext) {
+                updateRevisionForRevisionStatement(treeNode);
             }
         }
     }
 
+    @Override
+    public void exitRevision_stmts(Revision_stmtsContext ctx) {
+        exitLog("revisions", "");
+    }
+
     private void updateRevisionForRevisionStatement(final ParseTree treeNode) {
         final String revisionDateStr = stringFromNode(treeNode);
         try {
@@ -197,6 +205,7 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
             if ((revision != null) && (this.revision.compareTo(revision) < 0)) {
                 this.revision = revision;
                 moduleBuilder.setRevision(this.revision);
+                setLog("revision", this.revision.toString());
                 for (int i = 0; i < treeNode.getChildCount(); ++i) {
                     ParseTree child = treeNode.getChild(i);
                     if (child instanceof Reference_stmtContext) {
@@ -205,15 +214,17 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
                 }
             }
         } catch (ParseException e) {
-            final String message = "Failed to parse revision string: "
-                    + revisionDateStr;
+            final String message = "Failed to parse revision string: " + revisionDateStr;
             logger.warn(message);
         }
     }
 
     @Override
     public void enterImport_stmt(Import_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String importName = stringFromNode(ctx);
+        enterLog("import", importName, line);
+
         String importPrefix = null;
         Date importRevision = null;
 
@@ -227,51 +238,58 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
                 try {
                     importRevision = simpleDateFormat.parse(importRevisionStr);
                 } catch (ParseException e) {
-                    logger.warn("Failed to parse import revision-date: "
-                            + importRevisionStr);
+                    logger.warn("Failed to parse import revision-date at line " + line + ": " + importRevisionStr);
                 }
             }
         }
         moduleBuilder.addModuleImport(importName, importRevision, importPrefix);
+        setLog("import", "(" + importName + "; " + importRevision + "; " + importPrefix + ")");
+    }
+
+    @Override
+    public void exitImport_stmt(Import_stmtContext ctx) {
+        exitLog("import", "");
     }
 
     @Override
     public void enterAugment_stmt(YangParser.Augment_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String augmentPath = stringFromNode(ctx);
-        AugmentationSchemaBuilder builder = moduleBuilder.addAugment(
-                augmentPath, actualPath, ctx.getStart().getLine());
-        updatePath(augmentPath);
+        enterLog("augment", augmentPath, line);
+
+        AugmentationSchemaBuilder builder = moduleBuilder.addAugment(line, augmentPath);
 
         for (int i = 0; i < ctx.getChildCount(); i++) {
             ParseTree child = ctx.getChild(i);
             if (child instanceof Description_stmtContext) {
-                String desc = stringFromNode(child);
-                builder.setDescription(desc);
+                builder.setDescription(stringFromNode(child));
             } else if (child instanceof Reference_stmtContext) {
-                String ref = stringFromNode(child);
-                builder.setReference(ref);
+                builder.setReference(stringFromNode(child));
             } else if (child instanceof Status_stmtContext) {
-                Status status = parseStatus((Status_stmtContext) child);
-                builder.setStatus(status);
+                builder.setStatus(parseStatus((Status_stmtContext) child));
             } else if (child instanceof When_stmtContext) {
-                String when = stringFromNode(child);
-                builder.addWhenCondition(when);
+                builder.addWhenCondition(stringFromNode(child));
             }
         }
+
+        moduleBuilder.enterNode(builder);
+        actualPath.push(augmentPath);
     }
 
     @Override
     public void exitAugment_stmt(YangParser.Augment_stmtContext ctx) {
-        final String augment = actualPath.pop();
-        logger.debug("exiting augment " + augment);
+        moduleBuilder.exitNode();
+        exitLog("augment", actualPath.pop());
     }
 
     @Override
     public void enterExtension_stmt(YangParser.Extension_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String extName = stringFromNode(ctx);
+        enterLog("extension", extName, line);
+
         QName qname = new QName(namespace, revision, yangModelPrefix, extName);
-        ExtensionBuilder builder = moduleBuilder.addExtension(qname, ctx
-                .getStart().getLine());
+        ExtensionBuilder builder = moduleBuilder.addExtension(qname, line);
         parseSchemaNodeArgs(ctx, builder);
 
         String argument = null;
@@ -286,33 +304,46 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
         }
         builder.setArgument(argument);
         builder.setYinElement(yin);
+
+        moduleBuilder.enterNode(builder);
+        actualPath.push(extName);
+    }
+
+    @Override
+    public void exitExtension_stmt(YangParser.Extension_stmtContext ctx) {
+        moduleBuilder.exitNode();
+        exitLog("extension", actualPath.pop());
     }
 
     @Override
     public void enterTypedef_stmt(YangParser.Typedef_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String typedefName = stringFromNode(ctx);
-        QName typedefQName = new QName(namespace, revision, yangModelPrefix,
-                typedefName);
-        TypedefBuilder builder = moduleBuilder.addTypedef(typedefQName,
-                actualPath, ctx.getStart().getLine());
-        updatePath(typedefName);
-
-        builder.setPath(createActualSchemaPath(actualPath, namespace, revision,
-                yangModelPrefix));
+        enterLog("typedef", typedefName, line);
+
+        QName typedefQName = new QName(namespace, revision, yangModelPrefix, typedefName);
+        TypeDefinitionBuilder builder = moduleBuilder.addTypedef(line, typedefQName);
+        moduleBuilder.enterNode(builder);
+        actualPath.push(typedefName);
+
+        builder.setPath(createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix));
         parseSchemaNodeArgs(ctx, builder);
         builder.setUnits(parseUnits(ctx));
+        builder.setDefaultValue(parseDefault(ctx));
     }
 
     @Override
     public void exitTypedef_stmt(YangParser.Typedef_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
+        moduleBuilder.exitNode();
+        exitLog("typedef", actualPath.pop());
     }
 
     @Override
     public void enterType_stmt(YangParser.Type_stmtContext ctx) {
-        final String typeName = stringFromNode(ctx);
         final int line = ctx.getStart().getLine();
+        final String typeName = stringFromNode(ctx);
+        enterLog("type", typeName, line);
+
         final QName typeQName = parseQName(typeName);
 
         TypeDefinition<?> type = null;
@@ -330,41 +361,32 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
                 // check for types which must have body
                 checkMissingBody(typeName, moduleName, line);
                 // if there are no constraints, just grab default base yang type
-                type = YangTypesConverter.javaTypeForBaseYangType(actualPath,
-                        namespace, revision, typeName);
-                moduleBuilder.setType(type, actualPath);
+                type = YangTypesConverter.javaTypeForBaseYangType(actualPath, namespace, revision, typeName);
+                moduleBuilder.setType(type);
             } else {
                 if ("union".equals(typeName)) {
-                    List<String> typePath = new ArrayList<String>(actualPath);
-                    typePath.add(typeName);
-
-                    SchemaPath p = createActualSchemaPath(typePath, namespace, revision, yangModelPrefix);
-                    UnionTypeBuilder unionBuilder = moduleBuilder.addUnionType(actualPath, namespace, revision,
-                            line);
+                    SchemaPath p = createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix, typeName);
+                    UnionTypeBuilder unionBuilder = moduleBuilder.addUnionType(line, namespace, revision);
+                    moduleBuilder.enterNode(unionBuilder);
                     unionBuilder.setPath(p);
                 } else if ("identityref".equals(typeName)) {
-                    SchemaPath path = createActualSchemaPath(actualPath,
-                            namespace, revision, yangModelPrefix);
-                    moduleBuilder.addIdentityrefType(
-                            getIdentityrefBase(typeBody), actualPath, path,
-                            line);
+                    SchemaPath path = createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix, typeName);
+                    moduleBuilder.addIdentityrefType(line, path, getIdentityrefBase(typeBody));
                 } else {
-                    List<String> typePath = new ArrayList<String>(actualPath);
-                    typePath.add(typeName);
-
-                    type = parseTypeBody(typeName, typeBody, typePath,
-                            namespace, revision, yangModelPrefix);
-                    moduleBuilder.setType(type, actualPath);
+                    type = parseTypeWithBody(moduleName, typeName, typeBody, actualPath, namespace, revision,
+                            yangModelPrefix, moduleBuilder.getActualNode());
+                    moduleBuilder.setType(type);
                 }
             }
         } else {
-            type = parseUnknownTypeBody(typeQName, typeBody);
-            // mark parent node of this type statement as dirty
-            moduleBuilder.addDirtyNode(actualPath);
-            moduleBuilder.setType(type, actualPath);
+            type = parseUnknownTypeWithBody(moduleName, typeQName, typeBody, actualPath, namespace, revision, yangModelPrefix,
+                    moduleBuilder.getActualNode());
+            // add parent node of this type statement to dirty nodes
+            moduleBuilder.markActualNodeDirty();
+            moduleBuilder.setType(type);
         }
 
-        updatePath(typeName);
+        actualPath.push(typeName);
     }
 
     private QName parseQName(String typeName) {
@@ -379,55 +401,62 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
                 typeQName = new QName(null, null, prefix, name);
             }
         } else {
-            typeQName = new QName(namespace, revision, yangModelPrefix,
-                    typeName);
+            typeQName = new QName(namespace, revision, yangModelPrefix, typeName);
         }
         return typeQName;
     }
 
     @Override
     public void exitType_stmt(YangParser.Type_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
+        final String typeName = stringFromNode(ctx);
+        if ("union".equals(typeName)) {
+            moduleBuilder.exitNode();
+        }
+        exitLog("type", actualPath.pop());
     }
 
     @Override
     public void enterGrouping_stmt(YangParser.Grouping_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String groupName = stringFromNode(ctx);
-        QName groupQName = new QName(namespace, revision, yangModelPrefix,
-                groupName);
-        GroupingBuilder groupBuilder = moduleBuilder.addGrouping(groupQName,
-                actualPath, ctx.getStart().getLine());
-        updatePath("grouping");
-        updatePath(groupName);
-        parseSchemaNodeArgs(ctx, groupBuilder);
+        enterLog("grouping", groupName, line);
+
+        QName groupQName = new QName(namespace, revision, yangModelPrefix, groupName);
+        GroupingBuilder builder = moduleBuilder.addGrouping(ctx.getStart().getLine(), groupQName);
+        moduleBuilder.enterNode(builder);
+        actualPath.push(groupName);
+
+        builder.setPath(createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix));
+        parseSchemaNodeArgs(ctx, builder);
     }
 
     @Override
     public void exitGrouping_stmt(YangParser.Grouping_stmtContext ctx) {
-        String actContainer = actualPath.pop();
-        actContainer += "-" + actualPath.pop();
-        logger.debug("exiting " + actContainer);
+        moduleBuilder.exitNode();
+        exitLog("grouping", actualPath.pop());
     }
 
     @Override
     public void enterContainer_stmt(Container_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String containerName = stringFromNode(ctx);
-        QName containerQName = new QName(namespace, revision, yangModelPrefix,
-                containerName);
-        ContainerSchemaNodeBuilder containerBuilder = moduleBuilder
-                .addContainerNode(containerQName, actualPath, ctx.getStart().getLine());
-        updatePath(containerName);
+        enterLog("container", containerName, line);
 
-        containerBuilder.setPath(createActualSchemaPath(actualPath, namespace,
-                revision, yangModelPrefix));
-        parseSchemaNodeArgs(ctx, containerBuilder);
-        parseConstraints(ctx, containerBuilder.getConstraints());
+        QName containerQName = new QName(namespace, revision, yangModelPrefix, containerName);
+        SchemaPath path = createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix, containerName);
+
+        ContainerSchemaNodeBuilder builder = moduleBuilder.addContainerNode(line, containerQName, path);
+        moduleBuilder.enterNode(builder);
+        actualPath.push(containerName);
+
+        parseSchemaNodeArgs(ctx, builder);
+        parseConstraints(ctx, builder.getConstraints());
+        builder.setConfiguration(getConfig(ctx, moduleBuilder.getActualParent(), moduleName, line));
 
         for (int i = 0; i < ctx.getChildCount(); ++i) {
             final ParseTree childNode = ctx.getChild(i);
             if (childNode instanceof Presence_stmtContext) {
-                containerBuilder.setPresence(true);
+                builder.setPresence(true);
                 break;
             }
         }
@@ -435,23 +464,26 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
 
     @Override
     public void exitContainer_stmt(Container_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
+        moduleBuilder.exitNode();
+        exitLog("container", actualPath.pop());
     }
 
     @Override
     public void enterLeaf_stmt(Leaf_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String leafName = stringFromNode(ctx);
-        QName leafQName = new QName(namespace, revision, yangModelPrefix,
-                leafName);
-        LeafSchemaNodeBuilder leafBuilder = moduleBuilder.addLeafNode(
-                leafQName, actualPath, ctx.getStart().getLine());
-        updatePath(leafName);
+        enterLog("leaf", leafName, line);
+
+        QName leafQName = new QName(namespace, revision, yangModelPrefix, leafName);
+        SchemaPath schemaPath = createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix, leafName);
 
-        leafBuilder.setPath(createActualSchemaPath(actualPath, namespace,
-                revision, yangModelPrefix));
-        parseSchemaNodeArgs(ctx, leafBuilder);
-        parseConstraints(ctx, leafBuilder.getConstraints());
+        LeafSchemaNodeBuilder builder = moduleBuilder.addLeafNode(line, leafQName, schemaPath);
+        moduleBuilder.enterNode(builder);
+        actualPath.push(leafName);
+
+        parseSchemaNodeArgs(ctx, builder);
+        parseConstraints(ctx, builder.getConstraints());
+        builder.setConfiguration(getConfig(ctx, moduleBuilder.getActualParent(), moduleName, line));
 
         String defaultStr = null;
         String unitsStr = null;
@@ -463,63 +495,74 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
                 unitsStr = stringFromNode(child);
             }
         }
-        leafBuilder.setDefaultStr(defaultStr);
-        leafBuilder.setUnits(unitsStr);
+        builder.setDefaultStr(defaultStr);
+        builder.setUnits(unitsStr);
     }
 
     @Override
     public void exitLeaf_stmt(YangParser.Leaf_stmtContext ctx) {
-        final String actLeaf = actualPath.pop();
-        logger.debug("exiting " + actLeaf);
+        moduleBuilder.exitNode();
+        exitLog("leaf", actualPath.pop());
     }
 
     @Override
     public void enterUses_stmt(YangParser.Uses_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String groupingPathStr = stringFromNode(ctx);
-        moduleBuilder.addUsesNode(groupingPathStr, actualPath, ctx.getStart()
-                .getLine());
-        updatePath(groupingPathStr);
+        enterLog("uses", groupingPathStr, line);
+
+        UsesNodeBuilder builder = moduleBuilder.addUsesNode(line, groupingPathStr);
+
+        moduleBuilder.enterNode(builder);
+        actualPath.push(groupingPathStr);
     }
 
     @Override
     public void exitUses_stmt(YangParser.Uses_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
+        moduleBuilder.exitNode();
+        exitLog("uses", actualPath.pop());
     }
 
     @Override
     public void enterRefine_stmt(YangParser.Refine_stmtContext ctx) {
-        String refineString = stringFromNode(ctx);
+        final String refineString = stringFromNode(ctx);
+        enterLog("refine", refineString, ctx.getStart().getLine());
+
         RefineHolder refine = parseRefine(ctx);
         moduleBuilder.addRefine(refine, actualPath);
-        updatePath(refineString);
+        moduleBuilder.enterNode(refine);
+        actualPath.push(refineString);
     }
 
     @Override
     public void exitRefine_stmt(YangParser.Refine_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
+        moduleBuilder.exitNode();
+        exitLog("refine", actualPath.pop());
     }
 
     @Override
     public void enterLeaf_list_stmt(Leaf_list_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String leafListName = stringFromNode(ctx);
-        QName leafListQName = new QName(namespace, revision, yangModelPrefix,
-                leafListName);
-        LeafListSchemaNodeBuilder leafListBuilder = moduleBuilder
-                .addLeafListNode(leafListQName, actualPath, ctx.getStart()
-                        .getLine());
-        updatePath(leafListName);
+        enterLog("leaf-list", leafListName, line);
 
-        parseSchemaNodeArgs(ctx, leafListBuilder);
-        parseConstraints(ctx, leafListBuilder.getConstraints());
+        QName leafListQName = new QName(namespace, revision, yangModelPrefix, leafListName);
+        SchemaPath schemaPath = createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix, leafListName);
+
+        LeafListSchemaNodeBuilder builder = moduleBuilder.addLeafListNode(line, leafListQName, schemaPath);
+        moduleBuilder.enterNode(builder);
+        actualPath.push(leafListName);
+
+        parseSchemaNodeArgs(ctx, builder);
+        parseConstraints(ctx, builder.getConstraints());
+        builder.setConfiguration(getConfig(ctx, moduleBuilder.getActualParent(), moduleName, ctx.getStart().getLine()));
 
         for (int i = 0; i < ctx.getChildCount(); ++i) {
             final ParseTree childNode = ctx.getChild(i);
             if (childNode instanceof Ordered_by_stmtContext) {
                 final Ordered_by_stmtContext orderedBy = (Ordered_by_stmtContext) childNode;
                 final boolean userOrdered = parseUserOrdered(orderedBy);
-                leafListBuilder.setUserOrdered(userOrdered);
+                builder.setUserOrdered(userOrdered);
                 break;
             }
         }
@@ -527,23 +570,26 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
 
     @Override
     public void exitLeaf_list_stmt(YangParser.Leaf_list_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
+        moduleBuilder.exitNode();
+        exitLog("leaf-list", actualPath.pop());
     }
 
     @Override
     public void enterList_stmt(List_stmtContext ctx) {
-        final String containerName = stringFromNode(ctx);
-        QName containerQName = new QName(namespace, revision, yangModelPrefix,
-                containerName);
-        ListSchemaNodeBuilder listBuilder = moduleBuilder.addListNode(
-                containerQName, actualPath, ctx.getStart().getLine());
-        updatePath(containerName);
+        final int line = ctx.getStart().getLine();
+        final String listName = stringFromNode(ctx);
+        enterLog("list", listName, line);
+
+        QName listQName = new QName(namespace, revision, yangModelPrefix, listName);
+        SchemaPath schemaPath = createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix, listName);
+
+        ListSchemaNodeBuilder builder = moduleBuilder.addListNode(line, listQName, schemaPath);
+        moduleBuilder.enterNode(builder);
+        actualPath.push(listName);
 
-        listBuilder.setPath(createActualSchemaPath(actualPath, namespace,
-                revision, yangModelPrefix));
-        parseSchemaNodeArgs(ctx, listBuilder);
-        parseConstraints(ctx, listBuilder.getConstraints());
+        parseSchemaNodeArgs(ctx, builder);
+        parseConstraints(ctx, builder.getConstraints());
+        builder.setConfiguration(getConfig(ctx, moduleBuilder.getActualParent(), moduleName, line));
 
         String keyDefinition = "";
         for (int i = 0; i < ctx.getChildCount(); ++i) {
@@ -551,63 +597,68 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
             if (childNode instanceof Ordered_by_stmtContext) {
                 final Ordered_by_stmtContext orderedBy = (Ordered_by_stmtContext) childNode;
                 final boolean userOrdered = parseUserOrdered(orderedBy);
-                listBuilder.setUserOrdered(userOrdered);
+                builder.setUserOrdered(userOrdered);
             } else if (childNode instanceof Key_stmtContext) {
                 keyDefinition = stringFromNode(childNode);
-                List<QName> key = createListKey(keyDefinition, namespace,
-                        revision, yangModelPrefix);
-                listBuilder.setKeyDefinition(key);
+                List<QName> key = createListKey(keyDefinition, namespace, revision, yangModelPrefix);
+                builder.setKeyDefinition(key);
             }
         }
     }
 
     @Override
     public void exitList_stmt(List_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
+        moduleBuilder.exitNode();
+        exitLog("list", actualPath.pop());
     }
 
     @Override
     public void enterAnyxml_stmt(YangParser.Anyxml_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String anyXmlName = stringFromNode(ctx);
-        QName anyXmlQName = new QName(namespace, revision, yangModelPrefix,
-                anyXmlName);
-        AnyXmlBuilder anyXmlBuilder = moduleBuilder.addAnyXml(anyXmlQName,
-                actualPath, ctx.getStart().getLine());
-        updatePath(anyXmlName);
+        enterLog("anyxml", anyXmlName, line);
+
+        QName anyXmlQName = new QName(namespace, revision, yangModelPrefix, anyXmlName);
+        SchemaPath schemaPath = createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix, anyXmlName);
+
+        AnyXmlBuilder builder = moduleBuilder.addAnyXml(line, anyXmlQName, schemaPath);
+        moduleBuilder.enterNode(builder);
+        actualPath.push(anyXmlName);
 
-        anyXmlBuilder.setPath(createActualSchemaPath(actualPath, namespace,
-                revision, yangModelPrefix));
-        parseSchemaNodeArgs(ctx, anyXmlBuilder);
-        parseConstraints(ctx, anyXmlBuilder.getConstraints());
+        parseSchemaNodeArgs(ctx, builder);
+        parseConstraints(ctx, builder.getConstraints());
+        builder.setConfiguration(getConfig(ctx, moduleBuilder.getActualParent(), moduleName, line));
     }
 
     @Override
     public void exitAnyxml_stmt(YangParser.Anyxml_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
+        moduleBuilder.exitNode();
+        exitLog("anyxml", actualPath.pop());
     }
 
     @Override
     public void enterChoice_stmt(YangParser.Choice_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String choiceName = stringFromNode(ctx);
-        QName choiceQName = new QName(namespace, revision, yangModelPrefix,
-                choiceName);
-        ChoiceBuilder choiceBuilder = moduleBuilder.addChoice(choiceQName,
-                actualPath, ctx.getStart().getLine());
+        enterLog("choice", choiceName, line);
+
+        QName choiceQName = new QName(namespace, revision, yangModelPrefix, choiceName);
 
-        updatePath(choiceName);
-        choiceBuilder.setPath(createActualSchemaPath(actualPath, namespace,
-                revision, yangModelPrefix));
-        parseSchemaNodeArgs(ctx, choiceBuilder);
-        parseConstraints(ctx, choiceBuilder.getConstraints());
+        ChoiceBuilder builder = moduleBuilder.addChoice(line, choiceQName);
+        moduleBuilder.enterNode(builder);
+        actualPath.push(choiceName);
+
+        builder.setPath(createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix));
+        parseSchemaNodeArgs(ctx, builder);
+        parseConstraints(ctx, builder.getConstraints());
+        builder.setConfiguration(getConfig(ctx, moduleBuilder.getActualParent(), moduleName, line));
 
         // set 'default' case
         for (int i = 0; i < ctx.getChildCount(); i++) {
             ParseTree child = ctx.getChild(i);
             if (child instanceof Default_stmtContext) {
                 String defaultCase = stringFromNode(child);
-                choiceBuilder.setDefaultCase(defaultCase);
+                builder.setDefaultCase(defaultCase);
                 break;
             }
         }
@@ -615,66 +666,68 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
 
     @Override
     public void exitChoice_stmt(YangParser.Choice_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
+        moduleBuilder.exitNode();
+        exitLog("choice", actualPath.pop());
     }
 
     @Override
     public void enterCase_stmt(YangParser.Case_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String caseName = stringFromNode(ctx);
-        QName choiceQName = new QName(namespace, revision, yangModelPrefix,
-                caseName);
-        ChoiceCaseBuilder caseBuilder = moduleBuilder.addCase(choiceQName,
-                actualPath, ctx.getStart().getLine());
+        enterLog("case", caseName, line);
+
+        QName caseQName = new QName(namespace, revision, yangModelPrefix, caseName);
+        ChoiceCaseBuilder builder = moduleBuilder.addCase(line, caseQName);
+        moduleBuilder.enterNode(builder);
+        actualPath.push(caseName);
 
-        updatePath(caseName);
-        caseBuilder.setPath(createActualSchemaPath(actualPath, namespace,
-                revision, yangModelPrefix));
-        parseSchemaNodeArgs(ctx, caseBuilder);
-        parseConstraints(ctx, caseBuilder.getConstraints());
+        builder.setPath(createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix));
+        parseSchemaNodeArgs(ctx, builder);
+        parseConstraints(ctx, builder.getConstraints());
     }
 
     @Override
     public void exitCase_stmt(YangParser.Case_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
+        moduleBuilder.exitNode();
+        exitLog("case", actualPath.pop());
     }
 
     @Override
     public void enterNotification_stmt(YangParser.Notification_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String notificationName = stringFromNode(ctx);
-        QName notificationQName = new QName(namespace, revision,
-                yangModelPrefix, notificationName);
-        NotificationBuilder notificationBuilder = moduleBuilder
-                .addNotification(notificationQName, actualPath, ctx.getStart()
-                        .getLine());
-        updatePath(notificationName);
+        enterLog("notification", notificationName, line);
+
+        QName notificationQName = new QName(namespace, revision, yangModelPrefix, notificationName);
+        NotificationBuilder builder = moduleBuilder.addNotification(notificationQName, actualPath, line);
+        moduleBuilder.enterNode(builder);
+        actualPath.push(notificationName);
 
-        notificationBuilder.setPath(createActualSchemaPath(actualPath,
-                namespace, revision, yangModelPrefix));
-        parseSchemaNodeArgs(ctx, notificationBuilder);
+        builder.setPath(createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix));
+        parseSchemaNodeArgs(ctx, builder);
     }
 
     @Override
     public void exitNotification_stmt(YangParser.Notification_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
+        moduleBuilder.exitNode();
+        exitLog("notification", actualPath.pop());
     }
 
-    // Unknown types
+    // Unknown nodes
     @Override
     public void enterIdentifier_stmt(YangParser.Identifier_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String nodeParameter = stringFromNode(ctx);
+        enterLog("unknown-node", nodeParameter, line);
+
         QName nodeType = null;
 
         final String nodeTypeStr = ctx.getChild(0).getText();
         final String[] splittedElement = nodeTypeStr.split(":");
         if (splittedElement.length == 1) {
-            nodeType = new QName(null, null, yangModelPrefix,
-                    splittedElement[0]);
+            nodeType = new QName(null, null, yangModelPrefix, splittedElement[0]);
         } else {
-            nodeType = new QName(null, null, splittedElement[0],
-                    splittedElement[1]);
+            nodeType = new QName(null, null, splittedElement[0], splittedElement[1]);
         }
 
         QName qname;
@@ -683,100 +736,126 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
             if (splittedName.length == 2) {
                 qname = new QName(null, null, splittedName[0], splittedName[1]);
             } else {
-                qname = new QName(namespace, revision, yangModelPrefix,
-                        splittedName[0]);
+                qname = new QName(namespace, revision, yangModelPrefix, splittedName[0]);
             }
         } else {
-            qname = new QName(namespace, revision, yangModelPrefix,
-                    nodeParameter);
+            qname = new QName(namespace, revision, yangModelPrefix, nodeParameter);
         }
 
-        UnknownSchemaNodeBuilder builder = moduleBuilder.addUnknownSchemaNode(
-                qname, actualPath, ctx.getStart().getLine());
+        UnknownSchemaNodeBuilder builder = moduleBuilder.addUnknownSchemaNode(line, qname);
         builder.setNodeType(nodeType);
         builder.setNodeParameter(nodeParameter);
-        updatePath(nodeParameter);
-        builder.setPath(createActualSchemaPath(actualPath, namespace, revision,
-                yangModelPrefix));
+        actualPath.push(nodeParameter);
+        builder.setPath(createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix));
         parseSchemaNodeArgs(ctx, builder);
+        moduleBuilder.enterNode(builder);
     }
 
     @Override
     public void exitIdentifier_stmt(YangParser.Identifier_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
+        moduleBuilder.exitNode();
+        exitLog("unknown-node", actualPath.pop());
     }
 
     @Override
     public void enterRpc_stmt(YangParser.Rpc_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String rpcName = stringFromNode(ctx);
-        QName rpcQName = new QName(namespace, revision, yangModelPrefix,
-                rpcName);
-        RpcDefinitionBuilder rpcBuilder = moduleBuilder.addRpc(rpcQName,
-                actualPath, ctx.getStart().getLine());
-        updatePath(rpcName);
-
-        rpcBuilder.setPath(createActualSchemaPath(actualPath, namespace,
-                revision, yangModelPrefix));
+        enterLog("rpc", rpcName, line);
+
+        QName rpcQName = new QName(namespace, revision, yangModelPrefix, rpcName);
+        RpcDefinitionBuilder rpcBuilder = moduleBuilder.addRpc(line, rpcQName);
+        moduleBuilder.enterNode(rpcBuilder);
+        actualPath.push(rpcName);
+
+        rpcBuilder.setPath(createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix));
         parseSchemaNodeArgs(ctx, rpcBuilder);
     }
 
     @Override
     public void exitRpc_stmt(YangParser.Rpc_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
+        moduleBuilder.exitNode();
+        exitLog("rpc", actualPath.pop());
     }
 
     @Override
     public void enterInput_stmt(YangParser.Input_stmtContext ctx) {
-        updatePath("input");
+        final int line = ctx.getStart().getLine();
+        final String input = "input";
+        enterLog(input, input, line);
+
+        QName rpcQName = new QName(namespace, revision, yangModelPrefix, input);
+        SchemaPath path = createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix, input);
+
+        ContainerSchemaNodeBuilder builder = moduleBuilder.addRpcInput(path, rpcQName, line);
+        moduleBuilder.enterNode(builder);
+        actualPath.push(input);
+
+        parseSchemaNodeArgs(ctx, builder);
+        parseConstraints(ctx, builder.getConstraints());
     }
 
     @Override
     public void exitInput_stmt(YangParser.Input_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
+        moduleBuilder.exitNode();
+        exitLog("input", actualPath.pop());
     }
 
     @Override
     public void enterOutput_stmt(YangParser.Output_stmtContext ctx) {
-        updatePath("output");
+        final int line = ctx.getStart().getLine();
+        final String output = "output";
+        enterLog(output, output, line);
+
+        QName rpcQName = new QName(namespace, revision, yangModelPrefix, output);
+        SchemaPath path = createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix, output);
+
+        ContainerSchemaNodeBuilder builder = moduleBuilder.addRpcOutput(path, rpcQName, line);
+        moduleBuilder.enterNode(builder);
+        actualPath.push(output);
+
+        parseSchemaNodeArgs(ctx, builder);
+        parseConstraints(ctx, builder.getConstraints());
     }
 
     @Override
     public void exitOutput_stmt(YangParser.Output_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
+        moduleBuilder.exitNode();
+        exitLog("output", actualPath.pop());
     }
 
     @Override
     public void enterFeature_stmt(YangParser.Feature_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String featureName = stringFromNode(ctx);
-        QName featureQName = new QName(namespace, revision, yangModelPrefix,
-                featureName);
-        FeatureBuilder featureBuilder = moduleBuilder.addFeature(featureQName,
-                actualPath, ctx.getStart().getLine());
-        updatePath(featureName);
-
-        featureBuilder.setPath(createActualSchemaPath(actualPath, namespace,
-                revision, yangModelPrefix));
+        enterLog("feature", featureName, line);
+
+        QName featureQName = new QName(namespace, revision, yangModelPrefix, featureName);
+        FeatureBuilder featureBuilder = moduleBuilder.addFeature(line, featureQName);
+        moduleBuilder.enterNode(featureBuilder);
+        actualPath.push(featureName);
+
+        featureBuilder.setPath(createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix));
         parseSchemaNodeArgs(ctx, featureBuilder);
     }
 
     @Override
     public void exitFeature_stmt(YangParser.Feature_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
+        moduleBuilder.exitNode();
+        exitLog("feature", actualPath.pop());
     }
 
     @Override
     public void enterDeviation_stmt(YangParser.Deviation_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String targetPath = stringFromNode(ctx);
+        enterLog("deviation", targetPath, line);
+
         String reference = null;
         String deviate = null;
-        DeviationBuilder builder = moduleBuilder.addDeviation(targetPath,
-                actualPath, ctx.getStart().getLine());
-        updatePath(targetPath);
+        DeviationBuilder builder = moduleBuilder.addDeviation(line, targetPath);
+        moduleBuilder.enterNode(builder);
+        actualPath.push(targetPath);
 
         for (int i = 0; i < ctx.getChildCount(); i++) {
             ParseTree child = ctx.getChild(i);
@@ -798,27 +877,22 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
 
     @Override
     public void exitDeviation_stmt(YangParser.Deviation_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
-    }
-
-    @Override
-    public void enterConfig_stmt(YangParser.Config_stmtContext ctx) {
-        boolean configuration = parseConfig(ctx);
-        moduleBuilder.addConfiguration(configuration, actualPath);
+        moduleBuilder.exitNode();
+        exitLog("deviation", actualPath.pop());
     }
 
     @Override
     public void enterIdentity_stmt(YangParser.Identity_stmtContext ctx) {
+        final int line = ctx.getStart().getLine();
         final String identityName = stringFromNode(ctx);
-        final QName identityQName = new QName(namespace, revision,
-                yangModelPrefix, identityName);
-        IdentitySchemaNodeBuilder builder = moduleBuilder.addIdentity(
-                identityQName, actualPath, ctx.getStart().getLine());
-        updatePath(identityName);
-
-        builder.setPath(createActualSchemaPath(actualPath, namespace, revision,
-                yangModelPrefix));
+        enterLog("identity", identityName, line);
+
+        final QName identityQName = new QName(namespace, revision, yangModelPrefix, identityName);
+        IdentitySchemaNodeBuilder builder = moduleBuilder.addIdentity(identityQName, actualPath, line);
+        moduleBuilder.enterNode(builder);
+        actualPath.push(identityName);
+
+        builder.setPath(createActualSchemaPath(actualPath, namespace, revision, yangModelPrefix));
         parseSchemaNodeArgs(ctx, builder);
 
         for (int i = 0; i < ctx.getChildCount(); i++) {
@@ -832,16 +906,24 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
 
     @Override
     public void exitIdentity_stmt(YangParser.Identity_stmtContext ctx) {
-        final String actContainer = actualPath.pop();
-        logger.debug("exiting " + actContainer);
+        moduleBuilder.exitNode();
+        exitLog("identity", actualPath.pop());
     }
 
     public ModuleBuilder getModuleBuilder() {
         return moduleBuilder;
     }
 
-    private void updatePath(String containerName) {
-        actualPath.push(containerName);
+    private void enterLog(String p1, String p2, int line) {
+        logger.debug("entering " + p1 + " " + p2 + " (" + line + ")");
+    }
+
+    private void exitLog(String p1, String p2) {
+        logger.debug("exiting " + p1 + " " + p2);
+    }
+
+    private void setLog(String p1, String p2) {
+        logger.debug("setting " + p1 + " " + p2);
     }
 
 }